Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 创建列表<;CustomObject>;从列表<;其他对象>;,删除重复项。_C#_Linq - Fatal编程技术网

C# 创建列表<;CustomObject>;从列表<;其他对象>;,删除重复项。

C# 创建列表<;CustomObject>;从列表<;其他对象>;,删除重复项。,c#,linq,C#,Linq,有一个非常相关的问题:但是它不能同时处理删除重复项的问题 我有以下课堂示例: class Widget { public string OwnerName; public int SomeValue; } class Owner { public string Name; public string OtherData; } 我想根据小部件列表创建一个所有者列表,但只创建唯一的所有者名称 以下是我尝试过的: List<Owner> Owners =

有一个非常相关的问题:但是它不能同时处理删除重复项的问题

我有以下课堂示例:

class Widget
{
    public string OwnerName;
    public int SomeValue;
}

class Owner
{
    public string Name;
    public string OtherData;
}
我想根据小部件列表创建一个所有者列表,但只创建唯一的所有者名称

以下是我尝试过的:

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

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

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

这是因为LINQ扩展方法使用
IEqualityComparer
接口来比较对象。如果不定义自定义比较器(可以通过创建实现
IEqualityComparer
的单独类来实现),它将使用默认的相等比较器,该比较器使用类的
Equals()
GetHashCode()
定义。如果不重写它们,它将引用
Equals()
上的比较,并返回默认的对象哈希代码

可以定义一个自定义的
IEqualityComparer
(因为您正在按所有者序列调用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;
    }
}

一旦您这样做了,您编写的查询就可以正常工作。

您的所有者对象必须实现
IComparable
,才能使
Distinct
正常工作。您必须确定是什么使一个
所有者
与另一个
所有者

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

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

或者,您可以只在
Owner
上实现
Equals
GetHashCode
,您原来的方法就可以工作了。

我猜这个独特的方法试图从您实例化的
Owner
类中获取唯一的对象,为什么不选择字符串呢

试试这个:

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

然后从它们创建一个列表

使用Distinct equals确定两个元素是否相同。您可以为您的所有者实现equals。或者先选择名称,如下所示:

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

这意味着在每个只需要不同值的查询中都要记住这一点。实现IComparable非常重要neater@jay我认为
Equals()
GetHashCode()
应该这样做,因为内部
Distinct
只是尝试通过哈希代码将下一个元素添加到集合中,如果它已经存在,则跳过它。也就是说,
IComparable
也是一个不错的选择。+1感谢您展示了在LINQ中完成此操作的方法,这非常适合我正在处理的特定情况h、 这就是为什么我们如此爱你,对吧?:@Gluip:那不是一部尼克·凯奇的电影吗?你假设你的名字是主人的唯一标识符,我看我们的想法是相似的+1用于实际演示如何实现这些方法。对“正确”答案的艰难调用-@dlev显示了使用LINQ的解决方案,这非常好,因为这是一个一次性的方法,仅用于填充树视图(我在这种情况下的选择)。然而,James提供了一个非常好的例子,说明了如何做得更“防弹”,如果我在这门课上做得更多,他会适用的。@JYelton:不用担心,只要选择一个对你来说是最好的解决方案,并对另一个进行投票,我们都会很高兴的。对于当前的项目,我使用了@dlev的LINQ方法,但我相信在大多数情况下,实现Equals/GetHashCode是首选的方法。