给出以下代码。
class T {
public List<U> X { get; set; } /*.....*/
}
class U {
public int A { get; set; }
public int B { get; set; }
// other properties omit for easier testing
}
var l = new List<T> {
new T { X = new List<U> { new U { A = 0, B = 9 }, new U { A = 1, B = 8 } } },
new T { X = new List<U> { new U { A = 0, B = 9 }, new U { A = 1, B = 8 } } },
new T { X = new List<U> { new U { A = 2, B = 4 }, new U { A = 3, B = 5 } } },
new T { X = new List<U> { new U { A = 2, B = 4 }, new U { A = 3, B = 5 } } },
// ......
};
获得List<T>
的独特l
的最简洁方法是什么?预计回报将有两个子列表X
具有[{0,9},{1,8}]和[{2,4},{3,5}]。
根据对Enigmativity的回答的评论更新了代码:
interface IBase<I> { I A { get; set; } I B { get; set; } }
class T<I> {
public List<U<I>> X { get; set; } /*.....*/
}
class U<I> : IBase<I> {
public I A { get; set; }
public I B { get; set; }
// other properties omit for easier testing
}
var l = new List<T<int>> {
new T<int> { X = new List<U<int>> { new U<int> { A=0, B=9 }, new U<int> { A=1, B=8 } } },
new T<int> { X = new List<U<int>> { new U<int> { A=0, B=9 }, new U<int> { A=1, B=8 } } },
new T<int> { X = new List<U<int>> { new U<int> { A=2, B=4 }, new U<int> { A=3, B=5 } } },
new T<int> { X = new List<U<int>> { new U<int> { A=2, B=4 }, new U<int> { A=3, B=5 } } },
// ......
};
根据评论更新了样本数据:
var l = new List<T> {
new T { X = new List<U> { new U { A = 0, B = 9 }, new U { A = 1, B = 8 } } },
new T { X = new List<U> { new U { A = 0, B = 9 }, new U { A = 1, B = 8 } } },
new T { X = new List<U> { new U { A = 2, B = 4 }, new U { A = 3, B = 5 } } },
new T { X = new List<U> { new U { A = 2, B = 4 }, new U { A = 3, B = 5 } } },
new T { X = new List<U> {} }
// ......
};
答案 0 :(得分:3)
对于您给定的代码,最快的方法是实现IEqualityComparer<T>
并在标准LINQ .Distinct
运算符中使用它。
public class TEqualityComparer : IEqualityComparer<T>
{
public bool Equals(T t1, T t2)
{
if (t2 == null && t1 == null)
return true;
else if (t1 == null || t2 == null)
return false;
else
{
return
t1.X.Select(x => x.A).SequenceEqual(t2.X.Select(x => x.A))
&& t1.X.Select(x => x.B).SequenceEqual(t2.X.Select(x => x.B));
}
}
public int GetHashCode(T t)
{
return t.X.Select(x => x.A.GetHashCode())
.Concat(t.X.Select(x => x.B.GetHashCode()))
.Aggregate((x1, x2) => (x1 * 17 + 13) ^ x2);
}
}
然后你可以这样做:
IEnumerable<T> result = l.Distinct(new TEqualityComparer());
这给了你:
但是你希望结果为List<List<U>>
,那么你就这样做了:
List<List<U>> result =
l.Distinct(new TEqualityComparer())
.Select(t => t.X.ToList())
.ToList();
根据您更新的代码,这就是您所需要的:
public class TEqualityComparer<V> : IEqualityComparer<T<V>>
{
public bool Equals(T<V> t1, T<V> t2)
{
if (t2 == null && t1 == null)
return true;
else if (t1 == null || t2 == null)
return false;
else
{
return
t1.X.Select(x => x.A).SequenceEqual(t2.X.Select(x => x.A))
&& t1.X.Select(x => x.B).SequenceEqual(t2.X.Select(x => x.B));
}
}
public int GetHashCode(T<V> t)
{
return t.X.Select(x => x.A.GetHashCode())
.Concat(t.X.Select(x => x.B.GetHashCode()))
.Aggregate((x1, x2) => (x1 * 17 + 13) ^ x2);
}
}
你会这样称呼:
IEnumerable<T<int>> result = l.Distinct(new TEqualityComparer<int>());
...或:
List<List<U<int>>> result =
l.Distinct(new TEqualityComparer<int>())
.Select(t => t.X.ToList())
.ToList();
使用更新的数据,您现在需要做的就是将GetHashCode
更改为:
public int GetHashCode(T<V> t)
{
return t.X.Select(x => x.A.GetHashCode())
.Concat(t.X.Select(x => x.B.GetHashCode()))
.DefaultIfEmpty(0)
.Aggregate((x1, x2) => (x1 * 17 + 13) ^ x2);
}
您添加的数据适用于旧类。我将其更新为:
var l = new List<T<int>> {
new T<int> { X = new List<U<int>> { new U<int> { A=0, B=9 }, new U<int> { A=1, B=8 } } },
new T<int> { X = new List<U<int>> { new U<int> { A=0, B=9 }, new U<int> { A=1, B=8 } } },
new T<int> { X = new List<U<int>> { new U<int> { A=2, B=4 }, new U<int> { A=3, B=5 } } },
new T<int> { X = new List<U<int>> { new U<int> { A=2, B=4 }, new U<int> { A=3, B=5 } } },
new T<int> { X = new List<U<int>> { } },
// ......
};