C# Linq 与对象的一部分相交/除外
本文关键字:除外 一部分 Linq 对象 | 更新日期: 2023-09-27 18:34:22
我有一个类:
class ThisClass
{
private string a {get; set;}
private string b {get; set;}
}
我想使用 Linq 的相交和 except 方法,即:
private List<ThisClass> foo = new List<ThisClass>();
private List<ThisClass> bar = new List<ThisClass>();
然后我分别填写两个列表。例如,我想做以下事情(我知道这是不对的,只是伪代码):
foo[a].Intersect(bar[a]);
我该怎么做?
如果你想要一个要相交的单个属性的列表,那么所有其他漂亮的 LINQ 解决方案都可以正常工作。但!如果你想在整个类上相交,结果有一个List<ThisClass>
而不是List<string>
你必须编写自己的相等比较器。
foo.Intersect(bar, new YourEqualityComparer());
与Except
相同.
public class YourEqualityComparer: IEqualityComparer<ThisClass>
{
#region IEqualityComparer<ThisClass> Members
public bool Equals(ThisClass x, ThisClass y)
{
//no null check here, you might want to do that, or correct that to compare just one part of your object
return x.a == y.a && x.b == y.b;
}
public int GetHashCode(ThisClass obj)
{
unchecked
{
var hash = 17;
//same here, if you only want to get a hashcode on a, remove the line with b
hash = hash * 23 + obj.a.GetHashCode();
hash = hash * 23 + obj.b.GetHashCode();
return hash;
}
}
#endregion
}
也许
// returns list of intersecting property 'a' values
foo.Select(f => f.a).Intersect(bar.Select(b => b.a));
顺便说一句,财产a
应该是公共的。
不确定与相交和比较相比的速度,但怎么样:
//Intersect
var inter = foo.Where(f => bar.Any(b => b.a == f.a));
//Except - values of foo not in bar
var except = foo.Where(f => !bar.Any(b => b.a == f.a));
foo.Select(x=>x.a).Intersect(bar.Select(x=>x.a))
期望的效果到底是什么?你想得到一个由类中的所有a
组成的字符串列表,还是一个ThisClass
的列表,当两个ThisClass
实例通过唯一值a
标识时?
如果是前者,@lazyberezovksy和@Tilak的两个答案应该有效。如果是后者,则必须覆盖IEqualityComparer<ThisClass>
或IEquatable<ThisClass>
,以便Intersect
知道是什么使ThisClass
的两个实例等效:
private class ThisClass : IEquatable<ThisClass>
{
private string a;
public bool Equals(ThisClass other)
{
return string.Equals(this.a, other.a);
}
}
然后你可以打电话:
var intersection = foo.Intersect(bar);
我知道
这很旧,但你不能也覆盖类本身的 Equals 和 GetHashCode 吗?
class ThisClass
{
public string a {get; set;}
private string b {get; set;}
public override bool Equals(object obj)
{
// If you only want to compare on a
ThisClass that = (ThisClass)obj;
return string.Equals(a, that.a/* optional: not case sensitive? */);
}
public override int GetHashCode()
{
return a.GetHashCode();
}
}
你应该创建IEqualityComparer。您可以将 IEqualityComparer 传递给 Intersect() 方法。这将帮助您更轻松地获得列表(与条形相交)。
var intersectionList = foo.Intersect(bar, new ThisClassEqualityComparer()).ToList();
class ThisClassEqualityComparer : IEqualityComparer<ThisClass>
{
public bool Equals(ThisClass b1, ThisClass b2)
{
return b1.a == b2.a;
}
public int GetHashCode(Box bx)
{
// To ignore to compare hashcode, please consider this.
// I would like to force Equals() to be called
return 0;
}
}