C#Linq与对象的一部分相交/除外

时间:2012-05-17 09:51:45

标签: c# linq intersect except

我上课了:

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>();

然后我分别填写两个列表。我想做,例如(我知道这不对,只是伪代码),以下内容:

foo[a].Intersect(bar[a]);

我该怎么做?

7 个答案:

答案 0 :(得分:27)

也许

// returns list of intersecting property 'a' values
foo.Select(f => f.a).Intersect(bar.Select(b => b.a));

BTW属性a应该是公开的。

答案 1 :(得分:23)

如果你想要一个你想要交叉的单个属性的列表,那么所有其他漂亮的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
}

答案 2 :(得分:2)

foo.Select(x=>x.a).Intersect(bar.Select(x=>x.a))

答案 3 :(得分:2)

与交叉和比较相比,不确定这个速度,但是如何:

//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));

答案 4 :(得分:0)

期望的效果究竟是什么?当您通过{{1}的唯一值标识两个a实例时,是否需要获取由类中的所有ThisClass组成的字符串列表或ThisClass列表1}}?

如果是前者,@ lazyberezovksy和@Tilak的两个答案应该有效。如果是后者,则必须覆盖aIEqualityComparer<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);
     }
 }

答案 5 :(得分:0)

我知道这已经过时了,但你也不能只是覆盖Equals&amp;关于类本身的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();
  }
}

答案 6 :(得分:-2)

您应该创建IEqualityComparer。您可以将IEqualityComparer传递给Intersect()方法。这将帮助您更轻松地获取List(与bar相交)。

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;
    }

}