Ottieni un elenco di valori distinti in Elenco


175

In C #, supponiamo di avere una classe chiamata Note con tre variabili membro String.

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

E ho un elenco di tipo Nota:

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

Quale sarebbe il modo più pulito per ottenere un elenco di tutti i valori distinti nella colonna Autore?

Potrei scorrere l'elenco e aggiungere tutti i valori che non sono duplicati in un altro elenco di stringhe, ma questo sembra sporco e inefficiente. Ho la sensazione che ci sia una costruzione magica di Linq che lo farà in una riga, ma non sono stato in grado di inventare nulla.

Risposte:


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

Ciò restituirà una sequenza ( IEnumerable<string>) di Authorvalori - uno per valore univoco.


1
Notes.Select (x => x.Author) .AsParallel (). Distinct (); "AsParallel ()" potrebbe dare qualche vantaggio in termini di prestazioni, se non ci interessa l'ordine e abbiamo più articoli nell'elenco.
Sai,

1
@Kiquenet, distinto considerando il Defaultcomparatore di uguaglianza. msdn.microsoft.com/en-us/library/bb348436(v=vs.110).aspx
Georg Patscheider

Dobbiamo aggiungere ToList () prima di .Distinct ()?
Phan Đức Bình,

1
Non prima di Distinct () ma dopo, se stai cercando di convertire in un elenco. Esempio: Notes.Select (x => x.Author) .Distinct (). ToList ();
MTwiford,

87

Distinto la classe Note dall'autore

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

foreach(var item in DistinctItems)
{
    //Add to other List
}

1
Non è forse dovrebbe essere Notescome in Notes.GroupBy()con un plurale scome Noteconterrà solo una singola nota?
kkuilla,

30

Jon Skeet ha scritto una biblioteca chiamata morelinq che ha un DistinctBy()operatore. Vedi qui per l'implementazione. Il tuo codice sarebbe simile

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

Aggiornamento: dopo aver riletto la tua domanda, Kirk ha la risposta corretta se stai solo cercando un set distinto di autori.

Aggiunto esempio, diversi campi in DistinctBy:

res = res.DistinctBy(i => i.Name).DistinctBy(i => i.ProductId).ToList();

Eccellente grazie. Adoro che mantenga l'ordine corretto se ordino l'elenco prima di chiamare il metodo Distinct.
Vilhelm,

Ho aggiornato i collegamenti. LINQ è ora su Github e può essere installato tramite 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();

Usando la logica di cui sopra, possiamo ottenere gli unici Courses.


il tuo Distinto prima di ToList salva il mio tempo .. Sto facendo dopo ToList e dà l'errore che non può convertire l'elenco in Ienumerable.
Ajay2707,

Distinct non funzionerà qui perché per questo operatore ogni oggetto è unico in base all'hashcode dell'oggetto. Hai bisogno di qualcosa di simile a questo - github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs
Bose_geek

-2
mcilist = (from mci in mcilist select mci).Distinct().ToList();

Che cos'è esattamente il mci? Solo una tabella di esempio? La risposta è un po 'imbarazzante come è.
Brad Koch,

1
Sì, non penso che questo faccia quello che la mia domanda originale stava cercando (non importa che fosse un anno e mezzo fa e il progetto è da tempo finito). Da quello che posso dire, questo funzionerebbe se avessi già un elenco di stringhe Autore che potrebbero contenere duplicati, ma non potrei essere usato per estrarre tale elenco da un elenco di oggetti che hanno la stringa Autore come uno dei loro campi.
Darrel Hoffman,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.