2011-07-26 17 views
10

Tengo dos listas genéricas que contienen diferentes tipos, por el bien de ejemplo, vamos a llamarlos Products y Employees. Estoy tratando de encontrar los productos que se basan en la misma ubicación que los empleados, es decir, donde product.SiteId == emp.SiteId¿Cuál es la forma 'moderna' de encontrar elementos comunes en dos listas <T> de objetos?

List<Product> lstProds; 
List<Employees> lstEmps; 

Mi (vieja escuela) cerebro me está diciendo que utilizar un bucle forEach para encontrar las coincidencias, pero sospecho que hay una forma ('mejor'/terser/más rápida?) de hacerlo usando Linq. ¿Alguien puede iluminarme? Todos los ejemplos que he encontrado en línea tratan con listas de primitivos (cadenas/ints) y no son especialmente útiles.

Respuesta

17

, diría:

var products = from product in lstProds 
       join employee in lstEmps on product.SiteId equals employee.SiteId 
       select product; 

Sin embargo, si hay múltiples empleados con el mismo ID de sitio, obtendrá los productos varias veces. Se podría utilizar Distinct de solucionar este problema, o construir un conjunto de ID de sitio:

var siteIds = new HashSet<int>(lstEmps.Select(emp => emp.SiteId)); 

var products = lstProds.Where(product => siteIds.Contains(product.SiteId)); 

Eso suponiendo SiteId es un int - si se trata de un tipo anónimo o algo similar, es posible que desee un método de extensión extra:

public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source) 
{ 
    return new HashSet<T>(source); 
} 

continuación:

var siteIds = lstEmps.Select(emp => emp.SiteId).ToHashSet(); 
var products = lstProds.Where(product => siteIds.Contains(product.SiteId)); 

Alternativamente, si tiene pocos empleados, esto va a funcionar, pero es relativamente lento:

var products = lstProds.Where(p => lstEmps.Any(emp => p.SiteId == emp.SiteId)); 

añadir una llamada ToList a cualquiera de estos métodos para obtener una List<Product> en lugar de un IEnumerable<Product>.

+0

Muchas gracias Sr. Skeet. – 5arx

+0

Tuve que modificar la sintaxis un poco para que funcione, usar == para probar la igualdad es, al parecer, no es correcto? VS me dice que su 'expectativa de palabra clave contextual' es igual a ''. Reemplazar == con iguales parece ser el truco, pero en este momento no tengo idea de por qué? ¿Podría elaborar por favor ...? – 5arx

+1

@ 5arx: Lo siento, sí, corregido. Eso es solo parte de la sintaxis de la expresión de consulta: en realidad * no * proporciona una única expresión ('product.SiteId == employee.SiteId') para verificar cada par. En cambio, está proporcionando dos proyecciones ('product.SiteId' y' employee.SiteId') que se aplican a cada elemento de cada lado * una vez *, y luego se comparan las claves para la igualdad. –

Cuestiones relacionadas