我尝试使用 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>
.
或者,您可以使用直接采用 a的重载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-Name 对,您可以使用匿名类型并免费获得比较:
var MyItems = (from b in this.result
select new { b.Name, b.ID }).Distinct();
在此之后(再次假设您只需要 Name-ID 对),生成的对象将具有您需要的属性:
foreach(var item in MyItems)
Console.WriteLine("{0} -> {1}", item.ID, item.Name);
在C# 匿名类型上引用 MSDN :
因为匿名类型的 Equals 和 GetHashCode 方法是根据属性的 Equals 和 GetHashcode 方法定义的,所以相同匿名类型的两个实例只有在它们的所有属性都相等时才相等。
Enumerable.Distinct 方法 (IEnumerable) 通过使用默认的相等比较器来比较值,从序列中返回不同的元素。
请检查: https ://msdn.microsoft.com/en-us/library/bb348436.aspx
您需要将新项目添加到列表中,使用 foreach 考试:
foreach(var _item in result.Distinct()){
//Code here
}
好的 :)