如何从对象列表中获得一个不同的列表?

我有一个 List<MyClass> someList

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

我想知道如何得到一个新的不同的 List<MyClass> distinctListList<MyClass> someList,但只比较它与 Prop2

123805 次浏览

遗憾的是,在框架中没有真正简单的内置支持,但是您可以使用我在 莫林克中的 DistinctBy实现。

你会用:

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

(您可以只使用 DistinctBy实现。如果你更愿意使用微软的实现,我相信在系统中也有类似的东西。交互式组装 反应扩展。)

你需要使用 .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;
}
}

不要忘记 GetHashCode

用法:

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

您可以使用 GroupBy模拟 DistinctBy的效果,然后只使用每组中的第一个条目。不过,可能比其他实现要慢一些。

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();

我知道已经有一段时间了,但我需要最简单的答案,在这个时候(与。NET 4.5.1)我发现以下是我能得到的最直接的答案:

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

我的情况是,我有一个 ConcurrentDictionary,它看起来像: ConcurrentDictionary<long, FileModel>

ConcurrentDictionary Value 属性基本上就是我的 List<FileModel>

* FileModel 有一个 groupId,它不一定是唯一的(尽管我用来将 FileModel 对象添加到字典中的键(long)对于 FileModel 是唯一的)。

* 因示例中的清晰度而命名。

关键是,我在 ConcurrentDictionary 中有大量的 FileModel (想象一下100个) ,在这100个 FileModel 中有5个不同的 groupplds。

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

因此,如果我只有一个 FileModel 列表,代码看起来会像下面这样:

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

如果您希望通过多个字段实现 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();
}
}

然后使用比较器来区分你的列表:

var distinctedList = myList.Distinct(new MyComparer()).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();

由于引入了值元组,如果希望 LINQ 等效于 SQL 的 DISTINCT

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