Câu trả lời:
Bạn đang cố gắng để được khác biệt bởi nhiều hơn một lĩnh vực? Nếu vậy, chỉ cần sử dụng một loại ẩn danh và toán tử riêng biệt và nó sẽ ổn:
var query = doc.Elements("whatever")
.Select(element => new {
id = (int) element.Attribute("id"),
category = (int) element.Attribute("cat") })
.Distinct();
Nếu bạn đang cố gắng để có được một tập hợp các giá trị riêng biệt của loại "lớn hơn", nhưng chỉ nhìn vào một số tập hợp thuộc tính cho khía cạnh khác biệt, bạn có thể muốn được DistinctBy
triển khai trong MoreLINQ trong 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;
}
}
}
(Nếu bạn chuyển qua null
làm bộ so sánh, nó sẽ sử dụng bộ so sánh mặc định cho loại khóa.)
Chỉ cần sử dụng Distinct()
với so sánh của riêng bạn.
Ngoài câu trả lời của Jon Skeet, bạn cũng có thể sử dụng nhóm theo biểu thức để có được các nhóm duy nhất cùng với số lần lặp cho mỗi nhóm:
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() };
Đối với bất kỳ ai vẫn đang tìm kiếm; Đây là một cách khác để thực hiện một so sánh lambda tùy chỉnh.
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;
}
}
sau đó bạn có thể tạo tiện ích mở rộng cho linq Phân biệt có thể có trong lambda's
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> list, Func<T, T, bool> lambda)
{
return list.Distinct(new LambdaComparer<T>(lambda));
}
Sử dụng:
var availableItems = list.Distinct((p, p1) => p.Id== p1.Id);
Tôi hơi muộn với câu trả lời, nhưng bạn có thể muốn làm điều này nếu bạn muốn toàn bộ phần tử, không chỉ các giá trị bạn muốn nhóm theo:
var query = doc.Elements("whatever")
.GroupBy(element => new {
id = (int) element.Attribute("id"),
category = (int) element.Attribute("cat") })
.Select(e => e.First());
Điều này sẽ cung cấp cho bạn toàn bộ phần tử đầu tiên phù hợp với nhóm của bạn bằng cách chọn, giống như ví dụ thứ hai của Jon Skeets bằng cách sử dụng DistincBy, nhưng không thực hiện trình so sánh IEqualityComparer. DistincBy rất có thể sẽ nhanh hơn, nhưng giải pháp ở trên sẽ liên quan đến ít mã hơn nếu hiệu suất không phải là vấn đề.
// 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));
}
Vì chúng ta đang nói về việc có mọi yếu tố chính xác một lần, một "bộ" có ý nghĩa hơn đối với tôi.
Ví dụ với các lớp và IEqualityComparer đã triển khai:
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;
}
}
Hiện nay
List<Product> originalList = new List<Product> {new Product(1, "ad"), new Product(1, "ad")};
var setList = new HashSet<Product>(originalList, new ProductCompare()).ToList();
setList
sẽ có các yếu tố độc đáo
Tôi nghĩ về điều này trong khi xử lý .Except()
mà trả về một sự khác biệt thiết lập