2010-09-08 11 views
6

He 2 colecciones de lista en mi C# app..A y B.Usando LINQ no es igual

Tanto las colecciones tienen objeto de cliente que tiene identificador y el nombre attributes.Typically, A tiene más elementos que B.

Al usar Linq, quiero devolver solo aquellos clientes cuyo Id esté en A pero no en B.

¿Cómo puedo hacer esto?

+0

¿Qué quiere decir, "unir en una condición no es igual a"? –

+0

¿Puedes hacer tu pregunta un poco más específica? – FosterZ

Respuesta

18

Hay múltiples enfoques a seguir. El enfoque más limpio es utilizar el método de extensión Except si ha sobrescrito Equals y GetHashCode. Si no lo has hecho, hay otras opciones.

// have you overriden Equals/GetHashCode? 
IEnumerable<Customer> resultsA = listA.Except(listB); 

// no override of Equals/GetHashCode? Can you provide an IEqualityComparer<Customer>? 
IEnumerable<Customer> resultsB = listA.Except(listB, new CustomerComparer()); // Comparer shown below 

// no override of Equals/GetHashCode + no IEqualityComparer<Customer> implementation? 
IEnumerable<Customer> resultsC = listA.Where(a => !listB.Any(b => b.Id == a.Id)); 

// are the lists particularly large? perhaps try a hashset approach 
HashSet<int> customerIds = new HashSet<int>(listB.Select(b => b.Id).Distinct()); 
IEnumerable<Customer> resultsD = listA.Where(a => !customerIds.Contains(a.Id)); 

...

class CustomerComparer : IEqualityComparer<Customer> 
{ 
    public bool Equals(Customer x, Customer y) 
    { 
     return x.Id.Equals(y.Id); 
    } 

    public int GetHashCode(Customer obj) 
    { 
     return obj.Id.GetHashCode(); 
    } 
} 
+0

Gracias por sus comentarios ... De esta línea: listA.Where (a =>! ListB.Any (b => b.Id == a.Id));; cómo obtengo una tercera lista "C" que tiene esos objetos de clientes de A que no están en B? – Jimmy

+0

@Jimmy, 'List listC = listA.Where (a =>! ListB.Any (b => b.Id == a.Id)). ToList();' –

+0

Gracias Anthony Pegram! Esto funciona muy bien para mí ! Usé: listA.Where (a =>! ListB.Any (b => b.Id == a.Id)); enfoque. – Jimmy

5

Si override es igual para el objeto al cliente, a continuación, sólo tiene que utilizar

A.Except(B); 
4

Ampliando excepción, proporcionando su propio igualdad por lo que no es necesario para cambiar tu comportamiento Equals Tengo esto de aquí:

http://www.codeproject.com/KB/dotnet/LINQ.aspx#distinct

List<Customer> customersA = new List<Customer> { new Customer { Id = 1, Name = "A" }, new Customer { Id = 2, Name = "B" } }; 
List<Customer> customersB = new List<Customer> { new Customer { Id = 1, Name = "A" }, new Customer { Id = 3, Name = "C" } }; 

var c = (from custA in customersA 
     select custA.Id).Distinct() 
      .Except((from custB in customersB 
      select custB.Id).Distinct()); 
+0

En este caso, 'var c' sería' IEnumerable ', que representa una secuencia de los Ids únicos e incomparables de' customersA'. Para obtener los objetos 'Customer', este resultado debería ser usado nuevamente para extraer objetos de' customersA'. –