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