我正在尝试使用该类型的多个属性来比较两个相同类型的列表。
例如,
我有一个名为Details
的类public class Details
{
public int id;
public string symbol;
public string code;
}
我有两个列表:
List<Details> list1 = new List<Details>();
List<Details> list2 = new List<Details>();
list1.Add(new Details() { id=1,symbol="ANSI",code="NITE"});
list1.Add(new Details() { id = 1, symbol = "ANSI", code = "CALGO" });
list1.Add(new Details() { id = 1, symbol = "ANSI", code = "CANT" });
list1.Add(new Details() { id=2,symbol="ANSI",code="NITE"});
list1.Add(new Details() { id = 2, symbol = "ANSI", code = "CALGO" });
list1.Add(new Details() { id = 2, symbol = "ANSI", code = "CANT" });
list2.Add(new Details() { id = 1, symbol = "ANSI", code = "NITE" });
list2.Add(new Details() { id = 1, symbol = "ANSI", code = "CALGO" });
list2.Add(new Details() { id = 2, symbol = "ANSI", code = "NITE" });
我只希望List1中具有相同ID,符号但代码不同的数据。
因此,在上面的场景中,结果将如下所示。
list1.Add(new Details() { id = 1, symbol = "ANSI", code = "CANT" });
list1.Add(new Details() { id = 2, symbol = "ANSI", code = "CALGO" });
list1.Add(new Details() { id = 2, symbol = "ANSI", code = "CANT" });
如果可以通过Linq而不是使用foreach来实现这一点,那就太棒了。
我在下面试过,但那不正确。
var temp =list1.Where(x=>list2.Any(z=>x.id==z.id && string.Equals(x.symbol,z.symbol) && !string.Equals(x.code,z.code)));
答案 0 :(得分:4)
看起来你需要行来满足两个条件,而不是一个,以便输出:
id
和symbol
以及id
,symbol
和code
必须不匹配。以下是如何直接使用LINQ:
var tmp = list1.Where(x=>
list2.Any(z=>x.id==z.id && x.symbol==z.symbol)
&& !list2.Any(z => x.id==z.id && x.symbol==z.symbol && x.code==z.code));
基于应用De Morgan's laws的替代方案:
var tmp = list1.Where(x=>
list2.Any(z=>x.id==z.id && x.symbol==z.symbol)
&& list2.All(z => x.id!=z.id || x.symbol!=z.symbol || x.code!=z.code));
答案 1 :(得分:2)
1)我会先覆盖Equals
(以及GetHashCode
)
public class Details
{
public int id;
public string symbol;
public string code;
public override int GetHashCode()
{
return (id + symbol + code).GetHashCode();
}
public override bool Equals(object obj)
{
var other = obj as Details;
if (other == null) return false;
return id == other.id && symbol == other.symbol && code == other.code;
}
}
然后你可以使用Linq作为
var result = list1.Except(list2).ToList();
它会返回您期望的结果......
2)也可以在不更改Details
对象和实施自定义IEqualityComparer
public class DetailsComparer : IEqualityComparer<Details>
{
public bool Equals(Details x, Details y)
{
return x.id == y.id && x.symbol == y.symbol && x.code == y.code;
}
public int GetHashCode(Details obj)
{
return (obj.id + obj.symbol + obj.code).GetHashCode();
}
}
然后你的linq将是
var result = list1.Except(list2, new DetailsComparer()).ToList();
这些方法优于使用Any
和All
的O(n * n)算法
答案 2 :(得分:0)
当然,您可以像代码一样进行比较,但如果您希望代码具有更多结构,则可以覆盖方法Equals()
和运算符==
:
public class Details
{
public int id;
public string symbol;
public string code;
public override bool Equals(System.Object obj)
{
if (obj == null) {
return false;
}
Details detail = obj as Details;
if ((System.Object) detail == null) {
return false;
}
return (id == detail.id) && (symbol == detail.symbol);
}
public bool Equals(other) {
return this.id == other.id && this.symbole == other.symbol;
}
public override int GetHashCode() {
return id ^ symbol.GetHashCode();
}
}
然后你可以直接比较两个Detail对象。
答案 3 :(得分:-1)
这样做:
public class DetailsComparer : IEqualityComparer<Details>
{
public bool Equals(Details x, Details y)
=> x.id == y.id && x.symbol == y.symbol && x.code == y.code;
public int GetHashCode(Details obj)
=> obj.code.GetHashCode();
}
并且使用简单的这个
var x = list1.Except(list2, new DetailsComparer());
结果x:
1,ANSI,CANT
2,ANSI,CALGO
2,ANSI,CANT