query linq untuk mengembalikan nilai bidang yang berbeda dari daftar objek
91
classobj
{
int typeId; //10 types 0-9 string uniqueString; //this is unique
}
Asumsikan ada daftar dengan 100 elemen obj, tetapi hanya 10 typeID unik.
Apakah mungkin untuk menulis query LINQ mengembalikan 10 int unik dari daftar obj?
Bentuk kedua tampaknya menggunakan kelebihan Distinct yang tidak ada sejauh yang saya sadari.
Jon Skeet
Ups, hapus yang kedua, terima kasih @Jon Skeet, itu bisa dilakukan dengan IEqualityComparer
Arsen Mkrtchyan
3
Seperti yang disebutkan Jon Skeet, ini hanya akan mengembalikan properti yang ditentukan dalam Select.
Peet vd Westhuizen
59
Dengan asumsi Anda menginginkan objek penuh, tetapi hanya ingin berurusan dengan perbedaan typeID, tidak ada yang dibangun ke dalam LINQ untuk membuatnya mudah. (Jika Anda hanya menginginkan typeIDnilainya, mudah - proyeksikan itu dengan Selectdan kemudian gunakan Distinctpanggilan normal .)
Agar DistinctBy muncul, Anda perlu menambahkan namespace Microsoft.Ajax.Utilities
Shiljo Paulson
1
@Shil: Tidak, saya sedang menulis tentang DistinctBy di MoreLINQ. Tidak ada hubungannya dengan Microsoft.Ajax.Utilities.
Jon Skeet
Sekarang saya dapat melihat ada kelebihan Distinct di LINQ yang mengambil IEqualityComparer sebagai parameter dan mengembalikan daftar objek yang berbeda tergantung pada implementasi metode di IEqualityComparer
Dipendu Paul
1
@DipenduPaul: Ya, tapi itu tetap berarti membuat pembanding kesetaraan untuk properti tertentu, yang mengganggu dan membuatnya lebih sulit untuk dibaca. Jika Anda dapat mengambil ketergantungan MoreLINQ, saya pikir itu lebih bersih.
Jon Skeet
26
Jika hanya ingin menggunakan Linq murni, Anda dapat menggunakan groupby:
Jawaban:
sumber
Dengan asumsi Anda menginginkan objek penuh, tetapi hanya ingin berurusan dengan perbedaan
typeID
, tidak ada yang dibangun ke dalam LINQ untuk membuatnya mudah. (Jika Anda hanya menginginkantypeID
nilainya, mudah - proyeksikan itu denganSelect
dan kemudian gunakanDistinct
panggilan normal .)Di MoreLINQ kami memiliki
DistinctBy
operator yang dapat Anda gunakan:var distinct = list.DistinctBy(x => x.typeID);
Ini hanya berfungsi untuk LINQ ke Objek.
Anda dapat menggunakan pengelompokan atau pencarian, ini hanya agak mengganggu dan tidak efisien:
var distinct = list.GroupBy(x => x.typeID, (key, group) => group.First());
sumber
Jika hanya ingin menggunakan Linq murni, Anda dapat menggunakan groupby:
Jika Anda ingin metode digunakan di seluruh aplikasi, mirip dengan yang dilakukan MoreLinq :
public static IEnumerable<TSource> DistinctBy<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { HashSet<TKey> seenKeys = new HashSet<TKey>(); foreach (TSource element in source) { if (!seenKeys.Contains(keySelector(element))) { seenKeys.Add(keySelector(element)); yield return element; } } }
Dengan menggunakan metode ini untuk menemukan nilai yang berbeda hanya dengan menggunakan properti Id, Anda dapat menggunakan:
var query = objs.DistinctBy(p => p.TypeId);
Anda dapat menggunakan beberapa properti:
var query = objs.DistinctBy(p => new { p.TypeId, p.Name });
sumber
Tentu, gunakan
Enumerable.Distinct
.Diberikan koleksi
obj
(mis.foo
), Anda akan melakukan sesuatu seperti ini:var distinctTypeIDs = foo.Select(x => x.typeID).Distinct();
sumber
Saya pikir inilah yang Anda cari:
var objs= (from c in List_Objects orderby c.TypeID select c).GroupBy(g=>g.TypeID).Select(x=>x.FirstOrDefault());
Mirip dengan Returning a Distinct IQuerizable with LINQ?
sumber
.First
baik-baik saja, karena Anda tidak akan memiliki grup jika tidak ada sesuatu di dalamnya.GroupBy
untuk membuat ini lebih sederhana juga - lihat jawaban saya sebagai contoh.Jika hanya ingin menggunakan Linq, Anda dapat mengganti metode Equals dan GetHashCode .
Kelas produk :
public class Product { public string ProductName { get; set; } public int Id { get; set; } public override bool Equals(object obj) { if (!(obj is Product)) { return false; } var other = (Product)obj; return Id == other.Id; } public override int GetHashCode() { return Id.GetHashCode(); } }
Metode Utama :
static void Main(string[] args) { var products = new List<Product> { new Product{ ProductName="Product 1",Id = 1}, new Product{ ProductName="Product 2",Id = 2}, new Product{ ProductName="Product 4",Id = 5}, new Product{ ProductName="Product 3",Id = 3}, new Product{ ProductName="Product 4",Id = 4}, new Product{ ProductName="Product 6",Id = 4}, new Product{ ProductName="Product 6",Id = 4}, }; var itemsDistinctByProductName = products.Distinct().ToList(); foreach (var product in itemsDistinctByProductName) { Console.WriteLine($"Product Id : {product.Id} ProductName : {product.ProductName} "); } Console.ReadKey(); }
sumber
Saya ingin mengikat data tertentu ke dropdown dan itu harus berbeda. Saya melakukan hal berikut:
List<ClassDetails> classDetails; List<string> classDetailsData = classDetails.Select(dt => dt.Data).Distinct.ToList(); ddlData.DataSource = classDetailsData; ddlData.Databind();
Lihat apakah itu membantu
sumber