重複したアイテムを削除するためにlinqを試しました:
var MyItems = (from b in this.result
select new Item{ Name = b.Name, ID = b.ID }).Distinct();
結果を確認したところ、重複した項目が削除されていません。この問題を解決するにはどうすればよいですか?
デフォルトでDistinct()
はEqualityComparer<T>.Default
、を使用します。これには次のルールがあります。
デフォルトの等式比較機能であるDefaultは、IEquatableジェネリックインターフェイスを実装するタイプの値を比較するために使用されます。カスタムデータ型を比較するには、このインターフェイスを実装し、その型に独自のGetHashCodeメソッドとEqualsメソッドを提供する必要があります。
あなたの場合、これはItem
を実装する必要があることを意味しますIEquatable<Item>
。
または、オーバーロードをDistinct
直接IEqualityComparer<T>
使用することもできます。
Distinct() に比較オブジェクトを渡すことができます。
var MyItems = (from b in this.result
select new Item{ Name = b.Name, ID = b.ID }).Distinct(new ItemComparer());
カスタム比較クラスの例を次に示します。
// Custom comparer for the Item class
class ItemComparer: IEqualityComparer<Product>
{
// Items are equal if their names and IDs are equal.
public bool Equals(Item x, Item 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 items' properties are equal.
return x.ID == y.ID && x.Name == y.Name;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Item item)
{
//Check whether the object is null
if (Object.ReferenceEquals(item, null)) return 0;
//Get hash code for the Name field if it is not null.
int hashItemName = item.Name == null ? 0 : item.Name.GetHashCode();
//Get hash code for the ID field.
int hashItemID = item.ID.GetHashCode();
//Calculate the hash code for the item.
return hashItemName ^ hashItemID;
}
}
プリミティブではなくオブジェクトを比較しているので、Distinct
意味を定義するためにいくつかの作業を行う必要があります。
Distinct
以下を含むオーバーライドを見てください:http IEqualityComparer
:
//msdn.microsoft.com/en-us/library/bb338049.aspx
通常Distinct()
は、既定の等値比較子を使用してコレクションから要素を返します。
これにはカスタム比較子を使用できます。
// modified example from docs, not tested
class MyComparer : IEqualityComparer<Item>
{
// Items are equal if their ids are equal.
public bool Equals(Item x, Item 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 items properties are equal.
return x.ID == y.ID;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Product product)
{
//Check whether the object is null
if (Object.ReferenceEquals(item, null)) return 0;
//Get hash code for the ID field.
int hashProductId = product.ID.GetHashCode();
return hashProductId;
}
}
var myItems = (from b in this.result
select new Item{ Name = b.Name, ID = b.ID }).Distinct(new MyComparer());
この後どう使うか分からないのでItems
、ここでギャンブルです。
本当に ID と名前のペアだけが必要な場合は、匿名型を使用して無料で比較を取得できます。
var MyItems = (from b in this.result
select new { b.Name, b.ID }).Distinct();
この後 (また、必要なのは名前と ID のペアだけであると仮定します)、結果のオブジェクトには必要なプロパティが含まれます。
foreach(var item in MyItems)
Console.WriteLine("{0} -> {1}", item.ID, item.Name);
C# 匿名型に関する MSDN の引用:
匿名型の Equals および GetHashCode メソッドは、プロパティの Equals および GetHashcode メソッドに関して定義されるため、同じ匿名型の 2 つのインスタンスが等しいのは、それらのすべてのプロパティが等しい場合のみです。
リストに新しい項目を追加する必要があります。foreach 試験を使用します。
foreach(var _item in result.Distinct()){
//Code here
}
わかった :)