Obtenga una lista de valores distintos en Lista

175

En C #, digamos que tengo una clase llamada Nota con tres variables de miembro de cadena.

public class Note
{
    public string Title;
    public string Author;
    public string Text;
}

Y tengo una lista de tipo Nota:

List<Note> Notes = new List<Note>();

¿Cuál sería la forma más limpia de obtener una lista de todos los valores distintos en la columna Autor?

Podría recorrer la lista y agregar todos los valores que no son duplicados a otra lista de cadenas, pero esto parece sucio e ineficiente. Tengo la sensación de que hay una construcción mágica de Linq que hará esto en una sola línea, pero no he podido encontrar nada.

Darrel Hoffman
fuente

Respuestas:

332
Notes.Select(x => x.Author).Distinct();

Esto devolverá una secuencia ( IEnumerable<string>) de Authorvalores, uno por valor único.

Kirk Woll
fuente
1
Notas.Seleccione (x => x.Author) .AsParallel (). Distinct (); "AsParallel ()" podría brindar algún beneficio de rendimiento, si no nos importa el orden y tenemos más elementos en la lista.
Sai
1
@Kiquenet, distinto teniendo en cuenta el Defaultcomparador de igualdad. msdn.microsoft.com/en-us/library/bb348436(v=vs.110).aspx
Georg Patscheider
¿Necesitamos agregar ToList () antes de .Distinct ()?
Phan Đức Bình
1
No antes del Distinct () sino después, si está intentando convertir a una lista. Ej: Notas.Seleccione (x => x.Author) .Distinct (). ToList ();
MTwiford
87

Distinción de la clase de nota por autor

var DistinctItems = Note.GroupBy(x => x.Author).Select(y => y.First());

foreach(var item in DistinctItems)
{
    //Add to other List
}
atik sarker
fuente
1
¿No se supone que está Notesen Notes.GroupBy()un plural sya Noteque solo tendrá una sola nota?
kkuilla
30

Jon Skeet ha escrito una biblioteca llamada morelinq que tiene un DistinctBy()operador. Ver aquí para la implementación. Tu código se vería así

IEnumerable<Note> distinctNotes = Notes.DistinctBy(note => note.Author);

Actualización: después de volver a leer su pregunta, Kirk tiene la respuesta correcta si solo está buscando un conjunto distinto de Autores.

Muestra agregada, varios campos en DistinctBy:

res = res.DistinctBy(i => i.Name).DistinctBy(i => i.ProductId).ToList();
Dan Busha
fuente
Excelente gracias. Me encanta que mantenga el orden correcto si ordeno la lista antes de llamar al método Distinct.
Vilhelm
Actualicé los enlaces. MoreLINQ ahora está en Github y se puede instalar a través de Nuget:Install-Package morelinq
Chad Levy
2
public class KeyNote
{
    public long KeyNoteId { get; set; }
    public long CourseId { get; set; }
    public string CourseName { get; set; }
    public string Note { get; set; }
    public DateTime CreatedDate { get; set; }
}

public List<KeyNote> KeyNotes { get; set; }
public List<RefCourse> GetCourses { get; set; }    

List<RefCourse> courses = KeyNotes.Select(x => new RefCourse { CourseId = x.CourseId, Name = x.CourseName }).Distinct().ToList();

Al usar la lógica anterior, podemos obtener los Courses únicos .

Bhaskar
fuente
su Distinct before ToList me ahorra tiempo .. Lo estoy haciendo después de ToList y muestra el error que no puede convertir la lista a Ienumerable.
Ajay2707
Distinct no funcionará aquí porque para este operador cada objeto es único según el código hash del objeto. Necesita algo similar a esto: github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs
Bose_geek
-2
mcilist = (from mci in mcilist select mci).Distinct().ToList();
ravinderreddy Seeelam
fuente
¿Qué es exactamente mci? ¿Solo una tabla de ejemplo? La respuesta es un poco incómoda como es.
Brad Koch
1
Sí, no creo que esto haga lo que buscaba mi pregunta original (no importa, fue hace un año y medio y el proyecto ha terminado hace mucho tiempo). Por lo que puedo decir, esto funcionaría si ya tuviera una lista de cadenas de Autor que podría contener duplicados, pero no podría usarse para extraer dicha lista de una lista de objetos que tienen la cadena de Autor como uno de sus campos.
Darrel Hoffman