按属性分组是List<T>行不通的。
调整的最佳方法是什么?
var blocks = new List<Block>();
blocks.Add(new Block()
{
Id = 1,
Values = new List<int>() {1, 2}
});
blocks.Add(new Block()
{
Id = 1,
Values = new List<int>() { 2, 3 }
});
blocks.Add(new Block()
{
Id = 2,
Values = new List<int>() { 1, 2 }
});
blocks.Add(new Block()
{
Id = 2,
Values = new List<int>() { 2, 3 }
});
// here I have 2 groups, which is good
var g1 = blocks.GroupBy(b => b.Id);
// here I have 4 groups, I expected 2
var g2 = blocks.GroupBy(b => b.Values);
public class Block
{
public int Id { get; set; }
public List<int> Values { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
由于您要比较列表,因此必须提供一个比较器(哪些列表被视为相等?),如果且仅当当它们具有相同顺序的相同项目时,列表才相等:
{1, 2} != {1} // wrong items number
{1, 2} != {1, 2, 3} // wrong items number
{1, 2} != {1, 3} // wrong items values
{1, 2} != {2, 1} // wrong items order
{1, 2} == {1, 2}
Run Code Online (Sandbox Code Playgroud)
比较器可以是
public class MyListComparer<T> : IEqualityComparer<List<T>> {
public bool Equals(List<T> x, List<T> y) {
return Enumerable.SequenceEqual(x, y);
}
public int GetHashCode(List<T> obj) {
return obj == null ? -1 : obj.Count;
}
}
Run Code Online (Sandbox Code Playgroud)
和Linq
var g2 = blocks.GroupBy(b => b.Values, new MyListComparer<int>());
Run Code Online (Sandbox Code Playgroud)
编辑:如果我们想忽略顺序,我们可以实现一些不同的比较器:
public class MyLeanListComparer<T> : IEqualityComparer<List<T>> where T : IComparable<T> {
public bool Equals(List<T> x, List<T> y) {
if (ReferenceEquals(x, y))
return true;
else if (null == x || null == y)
return false;
return Enumerable.SequenceEqual(x.OrderBy(item => item), y.OrderBy(item => item));
}
public int GetHashCode(List<T> obj) {
return obj == null ? -1 : obj.Count;
}
}
Run Code Online (Sandbox Code Playgroud)