[英]How can I group by a list of elements?
I run into this issue again and again: how can I group a list of objects by a containing list of other objects? 我一次又一次地遇到这个问题:如何通过包含其他对象列表来对对象列表进行分组?
I have a list of objects of type A
and each of these objects has an property (lets call it ListProp
) which is a list also. 我有一个类型
A
的对象列表,每个对象都有一个属性(让我们称之为ListProp
),这也是一个列表。 ListProp
has elements of the type B
. ListProp
具有类型B
元素。 There are multiple elements of type A
with identically B
-objects in ListProp
, but the ListProp
property reference differs from element to element. 在
ListProp
有多个类型为A
且具有相同B
对象的元素,但ListProp
属性引用因元素而异。 How can I group these A
-objects the fastest way, where the B
-objects in ListProp
are identically? 如何以最快的方式对这些
A
对象进行分组,其中ListProp
中的B
对象是相同的?
Sample code: 示例代码:
class Program
{
static void Main(string[] args)
{
var exampleList = new List<A>
{
// Should be in first group
new A { ListProp = new List<B>
{
new B { Prop = new C { Number = 0 }},
new B { Prop = new C { Number = 1 }}
}},
// Should be in first group
new A { ListProp = new List<B>
{
new B { Prop = new C { Number = 0 }},
new B { Prop = new C { Number = 1 }}
}},
// Should be in second group
new A { ListProp = new List<B>
{
new B { Prop = new C { Number = 0 }},
new B { Prop = new C { Number = 1 }},
new B { Prop = new C { Number = 1 }}
}},
// Should be in third group
new A { ListProp = new List<B>
{
new B { Prop = new C { Number = 0 }},
new B { Prop = new C { Number = 0 }}
}}
};
// Doesn't work because the reference of ListProp is always different
var groupedExampleList = exampleList.GroupBy(x => x.ListProp);
}
}
class C
{
public int Number { get; set; }
public override bool Equals(object o)
{
if (o is C)
return Number.Equals(((C)o).Number);
else
return false;
}
}
class B
{
public C Prop { get; set; }
}
class A
{
public IList<B> ListProp { get; set; }
}
You can implement IEqualityComparer<List<B>>
and use it in the other GroupBy overload. 您可以实现
IEqualityComparer<List<B>>
并在其他GroupBy重载中使用它。
public class ListOfBEqualityComparer : IEqualityComparer<List<B>>
{
public bool Equals(List<B> x, List<B> y)
{
// you can also implement IEqualityComparer<B> and use the overload
return x.SequenceEqual(y);
}
public int GetHashCode(List<B> obj)
{
//implementation of List<T> may not work for your situation
return obj.GetHashCode();
}
}
Then you can use the overload 然后你可以使用过载
var groupedExampleList = exampleList.GroupBy(x => x.ListProp,
new ListOfBEqualityComparer());
Try this: 尝试这个:
GroupBy(x => String.Join(",", x.ListProp));
It will group by 0,1; 0,1; 0,1; 0,1,1; 0,1
它将按
0,1; 0,1; 0,1; 0,1,1; 0,1
分组0,1; 0,1; 0,1; 0,1,1; 0,1
0,1; 0,1; 0,1; 0,1,1; 0,1
0,1; 0,1; 0,1; 0,1,1; 0,1
accordingly. 0,1; 0,1; 0,1; 0,1,1; 0,1
。
I would approach this the following way: 我会通过以下方式来解决这个问题:
var data = exampleList.SelectMany(a=>a.ListProp.Select(x=>new{Key = x.Prop.Number, Value = a}))
.GroupBy(x=>x.Key)
.Select(g=>new {Number = g.Key, Items = g.ToList()});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.