简体   繁体   English

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

[英]How to get a distinct list from a List of objects?

I have a List<MyClass> someList .我有一个List<MyClass> someList

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

I would like to know how to get a new distinct List<MyClass> distinctList from List<MyClass> someList , but only comparing it to Prop2 .我想知道如何从List<MyClass> someList获得一个新的不同List<MyClass> distinctList ,但只将它与Prop2进行比较。

You can emulate the effect of DistinctBy using GroupBy and then just using the first entry in each group.您可以使用GroupBy模拟DistinctBy的效果,然后仅使用每个组中的第一个条目。 Might be a bit slower that the other implementations though.虽然可能比其他实现慢一点。

someList.GroupBy(elem=>elem.Prop2).Select(group=>group.First());

Unfortunately there's no really easy built-in support for this in the framework - but you can use the DistinctBy implementation I have in MoreLINQ .不幸的是,在框架中并没有真正简单的内置支持——但您可以使用我在MoreLINQ中的DistinctBy实现。

You'd use:你会使用:

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

(You can take just the DistinctBy implementation. If you'd rather use a Microsoft implementation, I believe there's something similar in the System.Interactive assembly of Reactive Extensions .) (您可以只采用DistinctBy实现。如果您更愿意使用 Microsoft 实现,我相信Reactive Extensions的 System.Interactive 程序集中有类似的东西。)

you need to use .Distinct(..);你需要使用.Distinct(..); extension method.扩展方法。 Here's a quick sample:这是一个快速示例:

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;
        }
    }

Do not forget about GetHashCode .不要忘记GetHashCode

Usage:用法:

List<Point> p = new List<Point>();
// add items
p.Distinct(new Comparer());

Override Equals(object obj) and GetHashCode() methods:覆盖Equals(object 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();
    }
}

and then just call:然后只需调用:

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

Since the introduction of value tuples, if you want a LINQ equivalent to SQL's DISTINCT自从引入了值元组,如果你想要一个相当于 SQL 的 DISTINCT 的 LINQ

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

If you would like to Distinct your list by multiple fields, You have to create an instance of IEqualityComparer interface:如果你想通过多个字段Distinct你的列表,你必须创建一个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();
    }
}

Then use the comparer to distinct your list:然后使用比较器来区分您的列表:

var distinctedList = myList.Distinct(new MyComparer()).ToList();

Create a class that implements the IEqualityComparer Interface that only checks for your Prop2-Property.创建一个实现IEqualityComparer接口的类,该接口仅检查您的 Prop2-Property。 You can then pass an instance of this class to the Distinct extension method.然后,您可以将此类的实例传递给 Distinct 扩展方法。

I know it's been a while, but I needed the simplest answer and at this time (with .NET 4.5.1) I found the following to be the most straight-forward answer I could get to:我知道这已经有一段时间了,但我需要最简单的答案,此时(使用 .NET 4.5.1)我发现以下是我能得到的最直接的答案:

IEnumerable<long> allIds = waitingFiles.Values.Select(wf => wf.groupId).Distinct();

My situation is that I have a ConcurrentDictionary that looks something like: ConcurrentDictionary<long, FileModel>我的情况是我有一个看起来像这样的 ConcurrentDictionary: ConcurrentDictionary<long, FileModel>

The ConcurrentDictionary Values property is basically my List<FileModel> . ConcurrentDictionary Values 属性基本上是我的List<FileModel>

*FileModel has a groupId that isn't necessarily unique (though, obviously the key (long) that I use to add the FileModel object into the dictionary is unique to the FileModel). *FileModel 有一个不一定唯一的 groupId(尽管,显然我用来将 FileModel 对象添加到字典中的键(长)对于 FileModel 是唯一的)。

*Named for clarity in the example. *为示例中的清晰起见命名。

The point is that I have a large number of FileModels (imagine 100) in the ConcurrentDictionary and within those 100 FileModels there are 5 different groupIds.关键是我在 ConcurrentDictionary 中有大量的 FileModel(假设有 100 个),在这 100 个 FileModel 中有 5 个不同的 groupId。

At this point I just need a list of the distinct groupId.此时我只需要一个不同 groupId 的列表。

So, again if I just had a list of FileModel the code would look like the following:所以,如果我只有一个 FileModel 列表,代码将如下所示:

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

I have a List<MyClass> someList .我有一个List<MyClass> someList

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

I would like to know how to get a new distinct List<MyClass> distinctList from List<MyClass> someList , but only comparing it to Prop2 .我想知道如何从List<MyClass> someList获得一个新的不同List<MyClass> distinctList ,但只将它与Prop2进行比较。

Simple way to remove duplications where all properties are equal:删除所有属性都相等的重复项的简单方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM