Отримайте список різних значень у списку


175

Скажімо, у C #, у мене є клас під назвою Note із трьома змінними String member.

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

У мене є список типу Примітка:

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

Який би був найчистіший спосіб отримати список усіх різних значень у стовпці "Автор"?

Я міг би перебрати список і додати всі значення, які не є дублікатами, до іншого списку рядків, але це здається брудним та неефективним. У мене є відчуття, що є якась магічна конструкція Linq, яка зробить це за один рядок, але мені нічого не вдалося придумати.

Відповіді:


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

Це поверне послідовність ( IEnumerable<string>) Authorзначень - одне на унікальне значення.


1
Примітки.Виберіть (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

Розрізнити клас Нота від автора

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();

Відмінно, дякую. Мені подобається, що він зберігає правильний порядок, якщо я замовляю список перед тим, як викликати метод розрізнення.
Вільгельм

Я оновив посилання. 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.


ваш відмінність перед ToList економить мій час .. Я роблю після ToList і видає помилку, яка не може перетворити список на безлічі.
Ajay2707

Тут розрізнення не буде працювати, оскільки для цього оператора кожен об’єкт унікальний на основі хеш-коду об'єкта. Вам потрібно щось подібне до цього - github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs
Bose_geek

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

Що саме є mci? Просто приклад таблиці? Відповідь трохи незручна, як і є.
Бред Кох

1
Так, я не думаю, що це те, що шукали в моєму первісному запитанні (неважливо, це було півтора роки тому, і проект давно закінчений). З того, що я можу сказати, це спрацювало, якби я вже мав список авторських рядків, який міг би містити дублікати, але не міг би бути використаний для вилучення такого списку зі списку об'єктів, у яких рядок Author є одним із своїх полів.
Даррель Гофман
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.