Uzyskaj listę różnych wartości na liście


175

W C # powiedz, że mam klasę o nazwie Note z trzema zmiennymi składowymi typu String.

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

I mam listę typu Uwaga:

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

Jaki byłby najczystszy sposób uzyskania listy wszystkich odrębnych wartości w kolumnie Autor?

Mógłbym iterować listę i dodać wszystkie wartości, które nie są duplikatami, do innej listy ciągów, ale wydaje się to brudne i nieefektywne. Mam wrażenie, że istnieje jakaś magiczna konstrukcja Linq, która zrobi to w jednej linii, ale nie byłem w stanie niczego wymyślić.

Odpowiedzi:


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

To zwróci sekwencję ( IEnumerable<string>) Authorwartości - po jednej na unikalną wartość.


1
Notes.Select (x => x.Author) .AsParallel (). Distinct (); „AsParallel ()” może przynieść pewne korzyści w zakresie wydajności, jeśli nie zależy nam na kolejności i mamy więcej elementów na liście.
Sai

1
@Kiquenet, odrębne, biorąc pod uwagę funkcję porównującą Defaultrówność. msdn.microsoft.com/en-us/library/bb348436(v=vs.110).aspx
Georg Patscheider

Czy musimy dodać ToList () przed .Distinct ()?
Phan Đức Bình

1
Nie przed Distinct (), ale po, jeśli próbujesz przekonwertować na listę. Np .: Notes.Select (x => x.Author) .Distinct (). ToList ();
MTwiford

87

Wyróżnij klasę Note według autora

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

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

1
Czy nie powinno to być Notestak samo Notes.GroupBy()z liczbą mnogą, sjak Notebędzie zawierać tylko jedną nutę?
kkuilla

30

Jon Skeet napisał bibliotekę o nazwie morelinq, która ma DistinctBy()operatora. Zobacz tutaj implementację. Twój kod będzie wyglądał

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

Aktualizacja: Po ponownym przeczytaniu pytania Kirk ma poprawną odpowiedź, jeśli szukasz tylko odrębnego zestawu autorów.

Dodano próbkę, kilka pól w DistinctBy:

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

Wspaniale, dziękuję. Podoba mi się to, że zachowuje właściwą kolejność, jeśli uporządkuję listę przed wywołaniem metody Distinct.
Vilhelm

Zaktualizowałem linki. LINQ jest teraz na Github i można go zainstalować przez 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();

Korzystając z powyższej logiki, możemy uzyskać unikalne Courses.


Twój Distinct przed ToList oszczędza mój czas .. Robię po ToList i podaje błąd, który nie może przekonwertować listy na Ienumerable.
Ajay2707

Odrębność nie zadziała tutaj, ponieważ dla tego operatora każdy obiekt jest unikalny na podstawie kodu skrótu obiektu. Potrzebujesz czegoś podobnego do tego - github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs
Bose_geek

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

Czym właściwie jest mci? Tylko przykładowy stół? Odpowiedź jest trochę niezręczna.
Brad Koch

1
Tak, nie sądzę, żeby to spełniało moje pierwotne pytanie (nieważne, że było to półtora roku temu, a projekt już dawno się skończył). Z tego, co wiem, zadziałałoby to, gdybym miał już listę ciągów znaków Autora, które mogą zawierać duplikaty, ale nie można ich użyć do wyodrębnienia takiej listy z listy obiektów, których jednym z pól jest ciąg znaków Autor.
Darrel Hoffman
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.