รับรายการค่าที่แตกต่างในรายการ


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 ()" อาจให้ประโยชน์ด้านประสิทธิภาพบางอย่างหากเราไม่สนใจเกี่ยวกับการสั่งซื้อและมีรายการเพิ่มเติมในรายการ
Sai

1
@ Kiquenet แตกต่างกันเมื่อเปรียบเทียบDefaultความเท่าเทียมกัน msdn.microsoft.com/en-us/library/bb348436(v=vs.110).aspx
Georg Patscheider

เราจำเป็นต้องเพิ่ม ToList () ก่อน. Distinct () หรือไม่?
ฟานĐứcBì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

Jon Skeet ได้เขียนห้องสมุดชื่อmorelinqซึ่งมีDistinctBy()โอเปอเรเตอร์ ดูที่นี่สำหรับการใช้งาน รหัสของคุณจะเป็นอย่างไร

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

อัปเดต: หลังจากอ่านคำถามของคุณอีกครั้งเคิร์กมีคำตอบที่ถูกต้องหากคุณแค่มองหาชุดของผู้แต่งที่แตกต่างกัน

เพิ่มตัวอย่างหลายสาขาใน DistinctBy:

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

ยอดเยี่ยมขอบคุณ ฉันชอบที่จะรักษาลำดับที่ถูกต้องหากฉันสั่งซื้อรายการก่อนที่จะเรียกใช้ Distinct method
Vilhelm

ฉันอัพเดทลิงค์ MoreLINQ เปิดให้ใช้บน Github แล้วและสามารถติดตั้งผ่าน 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();

โดยใช้ตรรกะข้างต้นเราสามารถได้รับประโยชน์ที่ไม่ซ้ำกันCourses


ความแตกต่างของคุณก่อน ToList ประหยัดเวลาของฉัน .. ฉันทำตาม ToList และให้ข้อผิดพลาดที่ไม่สามารถแปลงรายการเป็น Ienumerable ได้
Ajay2707

ความแตกต่างจะไม่ทำงานที่นี่เพราะสำหรับโอเปอเรเตอร์นี้ทุกวัตถุจะไม่ซ้ำกันตามแฮชโค้ดของวัตถุ คุณต้องคล้ายกับสิ่งนี้ - github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs
Bose_geek

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

mci คืออะไรกันแน่? แค่ตารางตัวอย่าง? คำตอบนั้นค่อนข้างน่าอึดอัดใจ
แบรดโคช์

1
ใช่ฉันไม่คิดว่าจะทำสิ่งที่คำถามเดิมของฉันกำลังมองหา (ไม่เป็นไรมันเป็นเวลาหนึ่งปีครึ่งแล้วและโครงการก็เสร็จสิ้นไปนานแล้ว) จากสิ่งที่ฉันสามารถบอกได้สิ่งนี้จะใช้ได้ถ้าฉันมีรายการของสตริงผู้เขียนซึ่งอาจมีรายการที่ซ้ำกัน แต่ไม่สามารถใช้เพื่อแยกรายการดังกล่าวจากรายการวัตถุที่มีสตริงผู้เขียนเป็นหนึ่งในเขตข้อมูลของพวกเขา
Darrel Hoffman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.