创建List< CustomObject>从列表中删除重复项

本文关键字:删除 列表 List CustomObject 创建 OtherObject | 更新日期: 2023-09-27 18:03:57

有一个非常相关的问题:创建列表从List但是,它不处理同时删除重复项。

我有以下类的例子:

class Widget
{
    public string OwnerName;
    public int SomeValue;
}
class Owner
{
    public string Name;
    public string OtherData;
}

我想创建一个基于Widgets列表的所有者列表,但只有唯一的所有者名称。

这是我尝试的:

List<Owner> Owners = MyWidgetList.Select(w => new Owner { Name = w.OwnerName }).Distinct().ToList();

问题是结果列表中有重复。我做错了什么?

创建List< CustomObject>从列表<OtherObject>中删除重复项

您需要为您的对象定义GetHashCode()Equals(),以定义自定义类型的相等性。否则,它将根据引用本身进行比较。

这是因为LINQ扩展方法使用IEqualityComparer接口来比较对象。如果您没有定义自定义比较器(您可以通过创建实现IEqualityComparer<Owner>的单独类来实现),它将使用默认的相等比较器,它使用类的Equals()GetHashCode()定义。如果你不覆盖它们,它会对Equals()进行引用比较,并返回默认的对象哈希码。

定义一个自定义的IEqualityComparer<Owner>(因为你在Owner序列上调用distinct)或为你的类添加一个Equals()GetHashCode()

public class Owner
{
    public string Name;
    public string OtherData;
    public override Equals(object other)
    {
        if (ReferenceEquals(this, other))
            return true;
        if (other == null)
            return false;
        // whatever your definition of equality is...
        return Name == other.Name && OtherData == other.OtherData;
    }
    public override int GetHashCode()
    {
        int hashCode = 0;
        unchecked
        {
           // whatever hash code computation you want, but for example...
            hashCode += 13 * Name != null ? Name.GetHashCode() : 0;
            hashCode += 13 * OtherData != null ? OtherData.GetHashCode() : 0;
        }
        return hashCode;
    }
}

一旦你这样做了,你写的查询将正常工作。

Owner的默认比较器不能正常工作(因为它只是使用引用相等),所以Distinct认为所有对象都是不同的。一个解决方案是使用两个Select s:

var owners = MyWidgetList.Select(w => w.OwnerName).Distinct().Select(w => new Owner { Name = w }).ToList();

或者,您可以在Owner上实现EqualsGetHashCode,并且您的原始方法将工作。

您的所有者对象必须实现IComparable<>才能使Distinct正常工作。您必须决定是什么使Owner与另一个Owner相同。

Distinct使用equals来确定两个元素是否相同。你可以为你的所有者实现equals。或者像这样先选择名称:

List<Owner> Owners = MyWidgetList.Select(w => w.OwnerName).Distinct()
 .Select(s=>new Owner{Name = s}.ToList();

我猜这个Distinct试图从您实例化的Owner类中获得唯一对象,为什么不选择字符串

试试这个:

List<string> OwnersStr = MyWidgetList.Select(w =>  w.OwnerName).Distinct().ToList();

然后创建一个列表