[英]Get distinct List<T> by properties of U of the list T.X?
Given the following the following code. 给出以下代码。
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 } } },
// ......
};
What's the most concise way to get the distinct List<T>
of the l
? 获取
l
的唯一List<T>
的最简洁方法是什么? The return is expected to have two sub-lists which X
has [{0,9}, {1,8}] and [{2,4}, {3,5}]. 期望返回包含两个子列表,其中
X
具有[{0,9},{1,8}]和[{2,4},{3,5}]。
Updated code based on comments to Enigmativity's answer: 根据对谜题答案的注释更新了代码:
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 } } },
// ......
};
Updated sample data as per comments: 根据注释更新了示例数据:
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> {} }
// ......
};
For your given code the quickest way is to implement an IEqualityComparer<T>
and use that in the standard LINQ .Distinct
operator. 对于给定的代码,最快的方法是实现
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);
}
}
Then you can do this: 然后,您可以执行以下操作:
IEnumerable<T> result = l.Distinct(new TEqualityComparer());
Which gives you: 这给你:
But you want the result as a List<List<U>>
so then you'd do this: 但是您希望将结果作为
List<List<U>>
因此您可以这样做:
List<List<U>> result =
l.Distinct(new TEqualityComparer())
.Select(t => t.X.ToList())
.ToList();
Based on your updated code, this is what you need: 根据您更新的代码,这是您需要的:
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);
}
}
You'd call it like: 您可以这样称呼它:
IEnumerable<T<int>> result = l.Distinct(new TEqualityComparer<int>());
...or: ...要么:
List<List<U<int>>> result =
l.Distinct(new TEqualityComparer<int>())
.Select(t => t.X.ToList())
.ToList();
With the updated data all you need to do to make this work now is to change GetHashCode
to this: 使用更新的数据,现在要做的就是将
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);
}
The data you added was for the old classes. 您添加的数据是针对旧类的。 I updated it to this:
我将其更新为:
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>> { } },
// ......
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.