C # Linq пересекается / за исключением одной части объекта

17

Я осмотрелся и не могу найти ничего, чтобы помочь здесь. У меня класс:

class ThisClass
{
  private string a {get; set;}
  private string b {get; set;}
}

Я хотел бы использовать методы Intersect и Except Linq, т. е.

private List<ThisClass> foo = new List<ThisClass>();
private List<ThisClass> bar = new List<ThisClass>();

Затем я заполняю два списка отдельно. Я хотел бы сделать, например (и я знаю, что это неправильно, просто псевдокод), следующее:

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

Как мне это сделать?

Спасибо за любую помощь:)

    
задан David Archer 17.05.2012 в 11:51
источник

7 ответов

21

Может

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

Свойство BTW a должно быть общедоступным.

    
ответ дан Sergey Berezovskiy 17.05.2012 в 11:54
источник
16

Если вам нужен список одного свойства, которое вы хотели бы пересечь, тогда все остальные красивые решения 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
}
    
ответ дан Patryk Ćwiek 17.05.2012 в 12:00
источник
2
foo.Select(x=>x.a).Intersect(bar.Select(x=>x.a))
    
ответ дан Tilak 17.05.2012 в 11:55
источник
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));
    
ответ дан Zach Johnson 14.01.2015 в 19:05
источник
0

Что такое желаемый эффект? Вы хотите получить список строк, состоящий из всех 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);     
    
ответ дан Avner Shahar-Kashtan 17.05.2012 в 12:02
источник
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();
  }
}
    
ответ дан tyr 10.11.2016 в 20:44
источник
-2

Вы должны создать 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;
    }

}
    
ответ дан Pongsathon.keng 17.05.2012 в 12:01
источник