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


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.


ваш 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();

Что такое mci? Просто пример таблицы? Ответ немного неловкий, как есть.
Брэд Кох

1
Да, я не думаю, что это делает то, что искал мой первоначальный вопрос (не говоря уже о том, что это было полтора года назад, и проект давно закончен). Насколько я могу судить, это сработало бы, если бы у меня уже был список строк Author, которые могли бы содержать дубликаты, но не могли использоваться для извлечения такого списка из списка объектов, в которых строка Author является одним из их полей.
Даррел Хоффман
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.