답변:
하나 이상의 필드로 구별하려고합니까? 그렇다면 익명 유형과 고유 연산자를 사용하십시오.
var query = doc.Elements("whatever")
.Select(element => new {
id = (int) element.Attribute("id"),
category = (int) element.Attribute("cat") })
.Distinct();
"더 큰"유형의 고유 한 값 세트를 가져 오려고 하지만 고유성 측면에 대한 특성의 일부 서브 세트 만보고자한다면 MoreLINQ 에서 DistinctBy
구현 된 것이 좋습니다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;
}
}
}
null
비교 자로 전달 하면 키 유형에 기본 비교기가 사용됩니다.
Distinct()
자신의 비교기와 함께 사용하십시오 .
Jon Skeet의 답변 외에도 그룹을 표현식별로 사용하여 각 그룹 반복에 대한 개수와 함께 고유 한 그룹을 얻을 수 있습니다.
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() };
여전히 찾고있는 사람이라면 다음은 커스텀 람다 비교기를 구현하는 또 다른 방법입니다.
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;
}
}
그런 다음 람다에 걸릴 수있는 linq Distinct에 대한 확장을 만들 수 있습니다
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> list, Func<T, T, bool> lambda)
{
return list.Distinct(new LambdaComparer<T>(lambda));
}
용법:
var availableItems = list.Distinct((p, p1) => p.Id== p1.Id);
답변에 약간 늦었지만 그룹화하려는 값뿐만 아니라 전체 요소를 원할 경우이 작업을 수행 할 수 있습니다.
var query = doc.Elements("whatever")
.GroupBy(element => new {
id = (int) element.Attribute("id"),
category = (int) element.Attribute("cat") })
.Select(e => e.First());
이렇게하면 DistinctBy를 사용하는 Jon Skeets의 두 번째 예제와 유사하지만 IEqualityComparer 비교기를 구현하지 않고도 선택에 따라 그룹과 일치하는 첫 번째 전체 요소가 제공됩니다. DistinctBy가 더 빠를 가능성이 높지만 성능에 문제가없는 경우 위의 솔루션에는 더 적은 코드가 포함됩니다.
// 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));
}
우리는 모든 요소를 정확히 한 번만 갖는 것에 대해 이야기하고 있기 때문에 "집합"이 더 의미가 있습니다.
클래스와 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;
}
}
지금
List<Product> originalList = new List<Product> {new Product(1, "ad"), new Product(1, "ad")};
var setList = new HashSet<Product>(originalList, new ProductCompare()).ToList();
setList
독특한 요소를 가질 것이다
나는 .Except()
세트 차이를 반환하는 것을 처리하면서 이것을 생각했다.