私はクラスを持っています:
class ThisClass
{
private string a {get; set;}
private string b {get; set;}
}
LinqのIntersectメソッドとExceptメソッドを使用したいと思います。
private List<ThisClass> foo = new List<ThisClass>();
private List<ThisClass> bar = new List<ThisClass>();
次に、2つのリストを別々に入力します。たとえば、次のようにしたいと思います(そして、これは正しくないことを知っていますが、単なる擬似コードです)。
foo[a].Intersect(bar[a]);
どうすればいいですか?
多分
// returns list of intersecting property 'a' values
foo.Select(f => f.a).Intersect(bar.Select(b => b.a));
BTWプロパティ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
}
交差および比較と比較した場合の速度はわかりませんが、次の点についてはどうでしょう。
//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
の一意の値によって2つのThisClass
インスタンスが識別された場合、クラス内のすべてのThisClass
で構成される文字列のリストを取得しますか、それともa
のリストを取得しますか?
前者の場合、@ lazyberezovksyと@Tilakからの2つの回答が機能するはずです。後者の場合は、IEqualityComparer<ThisClass>
またはIEquatable<ThisClass>
をオーバーライドして、Intersect
がThisClass
の2つのインスタンスを同等にする理由を認識できるようにする必要があります。
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();
}
}