Apakah Anda mencoba untuk tampil beda dengan lebih dari satu bidang? Jika demikian, cukup gunakan tipe anonim dan operator Distinct dan seharusnya tidak masalah:
var query = doc.Elements("whatever")
.Select(element => new {
id = (int) element.Attribute("id"),
category = (int) element.Attribute("cat") })
.Distinct();
Jika Anda mencoba mendapatkan sekumpulan nilai yang berbeda dari tipe "lebih besar", tetapi hanya melihat beberapa subset properti untuk aspek perbedaan, Anda mungkin ingin DistinctBy
seperti yang diterapkan di MoreLINQ di DistinctBy.cs
:
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IEqualityComparer<TKey> comparer)
{
HashSet<TKey> knownKeys = new HashSet<TKey>(comparer);
foreach (TSource element in source)
{
if (knownKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
(Jika Anda masuk null
sebagai pembanding, itu akan menggunakan pembanding default untuk jenis kunci.)
Cukup gunakan
Distinct()
dengan pembanding Anda sendiri.http://msdn.microsoft.com/en-us/library/bb338049.aspx
sumber
Selain jawaban Jon Skeet, Anda juga dapat menggunakan grup menurut ekspresi untuk mendapatkan grup unik bersama dengan hitungan untuk setiap iterasi grup:
var query = from e in doc.Elements("whatever") group e by new { id = e.Key, val = e.Value } into g select new { id = g.Key.id, val = g.Key.val, count = g.Count() };
sumber
Untuk siapa pun yang masih mencari; inilah cara lain untuk menerapkan pembanding lambda khusus.
public class LambdaComparer<T> : IEqualityComparer<T> { private readonly Func<T, T, bool> _expression; public LambdaComparer(Func<T, T, bool> lambda) { _expression = lambda; } public bool Equals(T x, T y) { return _expression(x, y); } public int GetHashCode(T obj) { /* If you just return 0 for the hash the Equals comparer will kick in. The underlying evaluation checks the hash and then short circuits the evaluation if it is false. Otherwise, it checks the Equals. If you force the hash to be true (by assuming 0 for both objects), you will always fall through to the Equals check which is what we are always going for. */ return 0; } }
Anda kemudian dapat membuat ekstensi untuk Linq Distinct yang dapat menggunakan lambda's
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> list, Func<T, T, bool> lambda) { return list.Distinct(new LambdaComparer<T>(lambda)); }
Pemakaian:
var availableItems = list.Distinct((p, p1) => p.Id== p1.Id);
sumber
Saya agak terlambat untuk jawabannya, tetapi Anda mungkin ingin melakukan ini jika Anda menginginkan seluruh elemen, tidak hanya nilai yang ingin Anda kelompokkan dengan:
var query = doc.Elements("whatever") .GroupBy(element => new { id = (int) element.Attribute("id"), category = (int) element.Attribute("cat") }) .Select(e => e.First());
Ini akan memberi Anda seluruh elemen pertama yang cocok dengan grup Anda dengan pilihan, seperti contoh kedua Jon Skeets menggunakan DistinctBy, tetapi tanpa menerapkan pembanding IEqualityComparer. DistinctBy kemungkinan besar akan lebih cepat, tetapi solusi di atas akan melibatkan lebih sedikit kode jika kinerja tidak menjadi masalah.
sumber
// First Get DataTable as dt // DataRowComparer Compare columns numbers in each row & data in each row IEnumerable<DataRow> Distinct = dt.AsEnumerable().Distinct(DataRowComparer.Default); foreach (DataRow row in Distinct) { Console.WriteLine("{0,-15} {1,-15}", row.Field<int>(0), row.Field<string>(1)); }
sumber
Karena kita berbicara tentang memiliki setiap elemen tepat satu kali, "set" lebih masuk akal bagi saya.
Contoh dengan penerapan kelas dan IEqualityComparer:
public class Product { public int Id { get; set; } public string Name { get; set; } public Product(int x, string y) { Id = x; Name = y; } } public class ProductCompare : IEqualityComparer<Product> { public bool Equals(Product x, Product y) { //Check whether the compared objects reference the same data. if (Object.ReferenceEquals(x, y)) return true; //Check whether any of the compared objects is null. if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) return false; //Check whether the products' properties are equal. return x.Id == y.Id && x.Name == y.Name; } public int GetHashCode(Product product) { //Check whether the object is null if (Object.ReferenceEquals(product, null)) return 0; //Get hash code for the Name field if it is not null. int hashProductName = product.Name == null ? 0 : product.Name.GetHashCode(); //Get hash code for the Code field. int hashProductCode = product.Id.GetHashCode(); //Calculate the hash code for the product. return hashProductName ^ hashProductCode; } }
Sekarang
List<Product> originalList = new List<Product> {new Product(1, "ad"), new Product(1, "ad")}; var setList = new HashSet<Product>(originalList, new ProductCompare()).ToList();
setList
akan memiliki elemen unikSaya memikirkan hal ini saat berurusan dengan
.Except()
yang mengembalikan perbedaan-setsumber