回答:
複数のフィールドで区別しようとしていますか?その場合は、匿名型とDistinct演算子を使用するだけで問題ありません。
var query = doc.Elements("whatever")
.Select(element => new {
id = (int) element.Attribute("id"),
category = (int) element.Attribute("cat") })
.Distinct();
「より大きな」タイプの個別の値のセットを取得しようとしているが、個別性の側面のプロパティの一部のサブセットのみを参照している場合DistinctBy
は、MoreLINQの実装として次のようにする必要があり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の回答に加えて、group by式を使用して、各グループの反復のカウントとともに一意のグループを取得することもできます。
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());
これにより、Jon SkeetsのDistinctByを使用した2番目の例のように、選択によってグループに一致する最初の要素全体が得られますが、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));
}
私たちはすべての要素を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()
セット差を返すものに対処しながら私はこれを考えました