Получить список различных значений в списке

175

В C #, скажем, у меня есть класс с именем Note с тремя переменными-членами String.

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

И у меня есть список типа Примечание:

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

Какой самый чистый способ получить список всех различных значений в столбце Автор?

Я мог бы перебрать список и добавить все значения, которые не являются дубликатами, в другой список строк, но это кажется грязным и неэффективным. У меня есть ощущение, что есть какая-то волшебная конструкция Linq, которая сделает это в одну строку, но я ничего не смог придумать.

Даррел Хоффман
источник

Ответы:

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

Это вернет последовательность ( IEnumerable<string>) Authorзначений - по одному на уникальное значение.

Кирк Волл
источник
1
Notes.Select (x => x.Author) .AsParallel (). Distinct (); «AsParallel ()» может дать некоторое преимущество в производительности, если мы не заботимся о порядке и имеем больше элементов в списке.
Саи
1
@Kiquenet, отличный, учитывая Defaultравенство равенства. msdn.microsoft.com/en-us/library/bb348436(v=vs.110).aspx
Георг Патшайдер
Нужно ли добавлять ToList () перед .Distinct ()?
Phan Đức Bình
1
Не до Distinct (), а после, если вы пытаетесь преобразовать в список. Пример: Notes.Select (x => x.Author) .Distinct (). ToList ();
MTwiford
87

Различить класс Note по автору

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

foreach(var item in DistinctItems)
{
    //Add to other List
}
Атик Саркер
источник
1
Разве это не должно быть так же, Notesкак во Notes.GroupBy()множественном числе, sпоскольку Noteбудет содержать только одну ноту?
kkuilla
30

Джон Скит написал библиотеку morelinq, в которой есть DistinctBy()оператор. Смотрите здесь для реализации. Ваш код будет выглядеть так

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

Обновление: после перечитывания вашего вопроса у Кирка будет правильный ответ, если вы просто ищете определенный набор авторов.

Добавлен пример, несколько полей в DistinctBy:

res = res.DistinctBy(i => i.Name).DistinctBy(i => i.ProductId).ToList();
Дан Буша
источник
Отлично, спасибо. Мне нравится, что он сохраняет правильный порядок, если я упорядочиваю список перед вызовом метода Distinct.
Вильгельм
Я обновил ссылки. MoreLINQ теперь на Github и может быть установлен через Nuget:Install-Package morelinq
Чад Леви
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();

Используя вышеупомянутую логику, мы можем получить уникальные Courses.

Bhaskar
источник
ваш Distinct до ToList экономит мое время .. Я делаю после ToList и выдает ошибку, которая не может преобразовать список в Ienumerable.
Ajay2707
Distinct не будет работать здесь, потому что для этого оператора каждый объект уникален на основе хеш-кода объекта. Вам нужно что-то похожее на это - github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs
Bose_geek
-2
mcilist = (from mci in mcilist select mci).Distinct().ToList();
ravinderreddy Seeelam
источник
Что такое mci? Просто пример таблицы? Ответ немного неловкий, как есть.
Брэд Кох
1
Да, я не думаю, что это делает то, что искал мой первоначальный вопрос (не говоря уже о том, что это было полтора года назад, и проект давно закончен). Насколько я могу судить, это сработало бы, если бы у меня уже был список строк Author, которые могли бы содержать дубликаты, но не могли использоваться для извлечения такого списка из списка объектов, в которых строка Author является одним из их полей.
Даррел Хоффман