Dapatkan daftar nilai berbeda di Daftar

175

Dalam C #, katakanlah saya memiliki kelas yang disebut Catatan dengan tiga variabel anggota String.

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

Dan saya memiliki daftar tipe Catatan:

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

Apa cara paling bersih untuk mendapatkan daftar semua nilai berbeda di kolom Penulis?

Saya bisa mengulangi daftar dan menambahkan semua nilai yang tidak duplikat ke daftar string lain, tetapi ini tampak kotor dan tidak efisien. Saya punya perasaan ada beberapa konstruksi Linq ajaib yang akan melakukan ini dalam satu baris, tetapi saya belum dapat menemukan apa pun.

Darrel Hoffman
sumber

Jawaban:

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

Ini akan mengembalikan urutan ( IEnumerable<string>) Authornilai - satu per nilai unik.

Kirk Woll
sumber
1
Notes. Pilih (x => x.Author) .AsParallel (). Distinct (); "AsParallel ()" mungkin memberikan beberapa manfaat kinerja, jika kami tidak peduli tentang pesanan dan memiliki lebih banyak item dalam daftar.
Sai
1
@Kiquenet, berbeda mengingat pembanding Defaultkesetaraan. msdn.microsoft.com/en-us/library/bb348436(v=vs.110).aspx
Georg Patscheider
Apakah kita perlu menambahkan ToList () sebelum .Distinct ()?
Phan Đức Bình
1
Tidak sebelum Perbedaan () tetapi setelah, jika Anda mencoba untuk mengkonversi ke daftar. Contoh: Notes. Pilih (x => x.Author) .Distinct (). Daftar ();
MTwiford
87

Bedakan kelas Note oleh Penulis

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

foreach(var item in DistinctItems)
{
    //Add to other List
}
atik sarker
sumber
1
Bukankah seharusnya Notesseperti Notes.GroupBy()jamak skarena Notehanya akan memegang satu Catatan tunggal?
kkuilla
30

Jon Skeet telah menulis perpustakaan bernama morelinq yang memiliki DistinctBy()operator. Lihat di sini untuk implementasinya. Kode Anda akan terlihat seperti

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

Pembaruan: Setelah membaca kembali pertanyaan Anda, Kirk memiliki jawaban yang benar jika Anda hanya mencari satu set Penulis yang berbeda.

Menambahkan sampel, beberapa bidang di DistinctBy:

res = res.DistinctBy(i => i.Name).DistinctBy(i => i.ProductId).ToList();
Dan Busha
sumber
Luar biasa terima kasih. Saya suka itu menjaga urutan yang benar jika saya memesan daftar sebelum saya memanggil metode Berbeda.
Vilhelm
Saya memperbarui tautan. MoreLINQ sekarang ada di Github dan dapat diinstal melalui 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();

Dengan menggunakan logika di atas, kita bisa mendapatkan unik Course.

Bhaskar
sumber
Perbedaan Anda sebelum ToList menghemat waktu saya .. Saya lakukan setelah ToList dan memberikan kesalahan yang tidak dapat mengkonversi daftar ke Ienumerable.
Ajay2707
Perbedaan tidak akan bekerja di sini karena untuk operator ini setiap objek unik berdasarkan kode hash objek. Anda memerlukan beberapa yang serupa dengan ini - github.com/morelinq/MoreLINQ/blob/master/MoreLinq/DistinctBy.cs
Bose_geek
-2
mcilist = (from mci in mcilist select mci).Distinct().ToList();
ravinderreddy Seeelam
sumber
Apa sebenarnya mci? Hanya tabel contoh? Jawabannya agak canggung.
Brad Koch
1
Ya, saya tidak berpikir ini melakukan apa yang dicari oleh pertanyaan awal saya (apalagi satu setengah tahun yang lalu dan proyek sudah lama selesai). Dari apa yang bisa saya katakan, ini akan berhasil jika saya sudah memiliki daftar string Penulis yang mungkin berisi duplikat, tetapi tidak dapat digunakan untuk mengekstrak daftar tersebut dari daftar objek yang memiliki string Penulis sebagai salah satu bidangnya.
Darrel Hoffman