C# 如何从对象列表中获取不同的列表?

C# 如何从对象列表中获取不同的列表?,c#,linq,class,list,properties,C#,Linq,Class,List,Properties,我有一个列表someList class MyClass { public int Prop1... public int Prop2... public int Prop3... } 我想知道如何从List someList中获取一个新的独特的List distinctList,但只将其与Prop2进行比较,不幸的是,框架中没有真正简单的内置支持,但是您可以使用我在中的实现 您可以使用: var distinctList = someList.DistinctBy(x

我有一个
列表someList

class MyClass
{
    public int Prop1...
    public int Prop2...
    public int Prop3...
}

我想知道如何从
List someList
中获取一个新的独特的
List distinctList
,但只将其与
Prop2
进行比较,不幸的是,框架中没有真正简单的内置支持,但是您可以使用我在中的实现

您可以使用:

var distinctList = someList.DistinctBy(x => x.Prop2).ToList();

(您可以通过实现来区分
。如果您更愿意使用Microsoft实现,我相信在System.Interactive assembly of中也有类似的功能。)

创建一个类,该类实现只检查Prop2属性的接口。然后,您可以将此类的实例传递给Distinct扩展方法。

您需要使用
.Distinct(…)扩展方法。
下面是一个快速示例:

public class Comparer : IEqualityComparer<Point>
    {
        public bool Equals(Point x, Point y)
        {
            return x.X == y.X;
        }

        public int GetHashCode(Point obj)
        {
            return (int)obj.X;
        }
    }

您可以通过使用
GroupBy
然后仅使用每组中的第一个条目来模拟
distinct的效果。可能比其他实现慢一点

someList.GroupBy(elem=>elem.Prop2).Select(group=>group.First());
重写等于(对象obj)GetHashCode()方法:

class MyClass
{
    public int Prop1 { get; set; }
    public int Prop2 { get; set; }
    public int Prop3 { get; set; }

    public override bool Equals(object obj)
    {
        return ((MyClass)obj).Prop2 == Prop2;
    }
    public override int GetHashCode()
    {
        return Prop2.GetHashCode();
    }
}
然后打电话:

List<MyClass> distinctList = someList.Distinct().ToList();
List distinctList=someList.Distinct().ToList();

我知道已经有一段时间了,但我需要最简单的答案,此时(使用.NET 4.5.1),我发现以下是我能得到的最直接的答案:

IEnumerable<long> allIds = waitingFiles.Values.Select(wf => wf.groupId).Distinct();
IEnumerable allIds=waitingFiles.Values.Select(wf=>wf.groupId.Distinct();
我的情况是,我有一本ConcurrentDictionary,看起来像:
ConcurrentDictionary

ConcurrentDictionary值属性基本上是我的
列表

class MyClass
{
    public int Prop1...
    public int Prop2...
    public int Prop3...
}
*FileModel有一个groupId,它不一定是唯一的(不过,很明显,我用于将FileModel对象添加到字典中的键(long)对于FileModel是唯一的)

*在示例中,为了清晰起见而命名

关键是我在ConcurrentDictionary中有大量的文件模型(想象100),在这100个文件模型中有5个不同的GroupID

此时,我只需要一个不同groupId的列表

因此,同样,如果我有一个FileModel列表,代码将如下所示:

IEnumerable <long> allIds = allFileModel.Select(fm => fm.groupId).Distinct();
IEnumerable allIds=allFileModel.Select(fm=>fm.groupId.Distinct();

只需使用Microsoft Ajax Ultility库的内置函数distinct,如示例:

首先包括图书馆

using Microsoft.Ajax.Utilities;
然后


如果要通过多个字段来区分列表,则必须创建
IEqualityComparer
接口的实例:

public class MyComparer : IEqualityComparer<MyModel>
{
    public bool Equals(MyModel x, MyModel y)
    {
       // compare multiple fields
        return
            x.Field1 == y.Field1 &&
            x.Field2 == y.Field2 &&
            x.Field3 == y.Field3 ;
    }

    public int GetHashCode(MyModel obj)
    {
        return 
            obj.Field1.GetHashCode() + 
            obj.Field2.GetHashCode() + 
            obj.Field3.GetHashCode();
    }
}

在所有属性相同的情况下删除重复的简单方法:

System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer();
serviceList = serviceList.GroupBy(s => jss.Serialize(s)).Select(group => group.First()).ToList();

自从引入值元组以来,如果希望LINQ等价于SQL的DISTINCT

items.GroupBy(item => (item.prop1, item.prop2, ...)).Select(group => group.First())

@Jon,在这些事情上使用MoreLINQ而不是在IEnumerable.Distinct上实现
IEqualityComparer
真的值得吗?@zerkms:我个人会使用MoreLINQ或反应式扩展,是的。。。包含它真的不需要太多努力,而且调用代码在我看来更具可读性。@Jon,我只是担心添加对第三方代码的依赖。另一方面,内置解决方案迫使我们编写臃肿的代码…:-S@Jon你知道为什么他们没有给Distinct添加一个重载,这个重载需要一个lambda吗?对于Contains的重载,同样的问题。@Ilya:这很简单:
foo.DistinctBy(x=>new{x.Prop1,x.Prop2})重复:如果我们调用
p.Distinct(),会发生什么不带
新比较器()
参数?通常,.NET将使用对象的相等方法(Equals和GetHashCode)。如果没有定义它们,它们将通过引用进行比较,因此,一个对象将只与自身相等。我们如何使用distinct,而不编写@ImanMahmoudinasab所说的“new Comparer()”?@Parsa编写distinct而不编写Comparer很容易
p.distinct()。只有当您想检查两个实例是否相同引用(相同内存)不相等(不同内存但属性值相等)时,Distinct with comparer才有用。@Parsa示例:
var a=new Person(“Iman”);var b=新员工(“伊曼”);var pList=新列表();pList.添加(a);pList.添加(b);pList.添加(a)pList
包含
a
两次,使用
pList.Distinc()
只会得到一个
a
和一个
b
。请注意,
a
b
具有相同的名称:
Iman
。所以
pList.Distinc().Count()
是2。但是对于比较器
pList.Distinc(new NameComparer()).Count()也是1。还可以处理多个属性:
someList.GroupBy(elem=>new{elem.Prop1,elem.Prop2,elem.Prop3})。选择(group=>group.First())这应该是可接受的答案。它不依赖于任何外部库和clean@TejasviHegde:与使用
DistinctBy
相比,它也有缺点:1)它需要更多的内存,因为它为每个元素构建了一个组;2) 它不能流式传输结果-它必须在生成任何元素之前完全读取
someList
。我想说MoreLINQ方法更干净。@JonSkeet谢谢!我没有从这个角度思考:)顺便说一句,我只是浏览了你们库的代码,我喜欢它的编码风格和简洁的实现!这真的帮了我很大的忙。我们还可以在末尾添加.ToList()。顺便说一句,真的很有帮助
System.Web.Script.Serialization.JavaScriptSerializer jss = new System.Web.Script.Serialization.JavaScriptSerializer();
serviceList = serviceList.GroupBy(s => jss.Serialize(s)).Select(group => group.First()).ToList();
items.GroupBy(item => (item.prop1, item.prop2, ...)).Select(group => group.First())