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.