2012-05-17 14 views
18

He echado un vistazo y no encuentro nada para ayudar aquí. Tengo una clase:C# Linq se cruzan/excepto con una parte del objeto

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

me gustaría usar el Intersect y Salvo métodos de LINQ, es decir .:

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

Entonces llenar las dos listas por separado. Me gustaría hacer, por ejemplo (y sé que esto no es correcto, sólo pseudocódigo), lo siguiente:

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

¿Cómo voy a hacer esto?

Gracias por cualquier ayuda :)

+0

¿Qué es lo que quieres? Explica en palabras qué quieres de esta línea 'foo [a]. Intersecta (bar [a]);'. –

Respuesta

25

Tal

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

BTW propiedad a deben ser públicos.

+0

Agradable, simple, hace justo lo que necesito. Gracias a ti y a todos los que responden. –

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

Si desea una lista de una sola propiedad que le gustaría intersectar, entonces todas las demás soluciones LINQ funcionan muy bien. PERO! Sin embargo, si desea cruzarse en una clase completa y, como resultado, tiene un List<ThisClass> en lugar de List<string>, tendrá que escribir su propio comparador de igualdad.

foo.Intersect(bar, new YourEqualityComparer()); 

mismo con 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

Debería crear IEqualityComparer. Puede pasar el método IEqualityComparer a Intersect(). Esto le ayudará a obtener la Lista (que se cruzan con la barra) más fácil.

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

} 
+1

No debería devolver '0' desde el código hash como este. Eso va a matar por completo el rendimiento. En su lugar, debe usar el código hash de 'a'. – Servy

0

¿Cuál es exactamente el efecto deseado? ¿Desea obtener una lista de cadenas compuestas de todos los a en sus clases, o una lista de ThisClass, cuando dos instancias ThisClass se identifican mediante valores únicos de a?

Si es la primera, las dos respuestas de @lazyberezovksy y @Tilak deberían funcionar. Si es esto último, usted tiene que anular IEqualityComparer<ThisClass> o IEquatable<ThisClass> modo que Intersect sabe lo que hace que dos instancias de ThisClass equivalente:

private class ThisClass : IEquatable<ThisClass> 
{ 
    private string a; 

    public bool Equals(ThisClass other) 
    { 
     return string.Equals(this.a, other.a); 
    } 
} 

a continuación, puedes llamar:

var intersection = foo.Intersect(bar);  
+1

Siempre debe sobrescribir 'GetHashCode' al implementar' IEquatable'. Como no lo haces, esto no funcionará. – Servy

3

No está seguro de la velocidad de este en comparación con intersectar y comparar, pero ¿qué hay de:

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

Este es un algoritmo O (n * m) mientras que 'Intersecar' y 'Excepto' son ambos 'O (n + m)'. Eso te hace mucho peor. También itera 'bar' varias veces, lo que puede ser un problema importante en todo tipo de situaciones (puede no dar los mismos resultados en cada iteración, podría consultar una base de datos o realizar cálculos costosos en cada iteración, podría tener efectos secundarios) causado cuando se itera, etc. – Servy

0

Sé que esto es viejo, pero no se pudo ¿Igualmente solo anula el valor & GetHashCode en la clase?

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(); 
    } 
} 
Cuestiones relacionadas