我一次又一次地遇到这个问题:如何通过包含其他对象的列表对对象列表进行分组?
我有一个A
类型的对象列表,每个对象都有一个属性(让我们称之为ListProp
),这也是一个列表。 ListProp
包含B
类型的元素。 A
类型中有多个元素具有相同的B
- ListProp
中的对象,但ListProp
属性引用因元素而异。如何以最快的方式对这些A
- 对象进行分组,B
- ListProp
中的对象相同?
示例代码:
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; }
}
答案 0 :(得分:6)
您可以实施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();
}
}
然后你可以使用重载
var groupedExampleList = exampleList.GroupBy(x => x.ListProp,
new ListOfBEqualityComparer());
答案 1 :(得分:4)
试试这个:
GroupBy(x => String.Join(",", x.ListProp));
它会相应地按0,1; 0,1; 0,1; 0,1,1; 0,1
进行分组。
答案 2 :(得分:0)
我会按以下方式处理:
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()});