2012-08-15 36 views
6

No puedo encontrar un ejemplo específico de esto, así que estoy publicando la pregunta. Cualquier ayuda apreciada.Comparando dos grandes listas genéricas

Tengo dos grandes listas genéricas, ambas con más de 300K elementos.

Estoy recorriendo la primera lista para recuperar información y generar un nuevo elemento para una nueva lista sobre la marcha, pero necesito buscar dentro de la segunda lista y devolver un valor, basado en TRES criterios coincidentes, si se encuentra para agregar a la lista, sin embargo, como se puede imaginar, hacer esto 300k * 300k veces lleva tiempo.

¿Hay alguna forma de que pueda hacer esto de manera más eficiente?

Mi código:

var reportList = new List<StocksHeldInCustody>(); 
foreach (var correctDepotHolding in correctDepotHoldings) 
    { 
    var reportLine = new StocksHeldInCustody(); 
    reportLine.ClientNo = correctDepotHolding.ClientNo; 
    reportLine.Value = correctDepotHolding.ValueOfStock; 
    reportLine.Depot = correctDepotHolding.Depot; 
    reportLine.SEDOL = correctDepotHolding.StockCode; 
    reportLine.Units = correctDepotHolding.QuantityHeld; 
    reportLine.Custodian = "Unknown"; 
    reportLine.StockName = correctDepotHolding.StockR1.Trim() + " " + correctDepotHolding.StockR2.Trim(); 

    //Get custodian info 

    foreach (var ccHolding in ccHoldList) 
    { 
     if (correctDepotHolding.ClientNo != ccHolding.ClientNo) continue; 
     if (correctDepotHolding.Depot != ccHolding.Depot) continue; 
     if (correctDepotHolding.StockCode != ccHolding.StockCode) continue; 
     if (correctDepotHolding.QuantityHeld != ccHolding.QuantityHeld) continue; 
     reportLine.Custodian = ccHolding.Custodian; 
     break; 
    } 
    reportList.Add(reportLine); 
    } 
+0

crear un hash de todos los VARs juntos en el objeto y sólo comprobar estos, debe correr rápido luego – EaterOfCode

+1

¿Cuál es la fuente de los datos? Si se trata de una base de datos decente, podría ser mejor hacerlo de ese lado. –

+0

Actualicé mi respuesta genérica con detalles sobre cómo realizar una combinación externa en linq – Arkiliknam

Respuesta

5

Como Pranay dice, una combinación es probablemente lo que quiere:

var query = from correct in correctDepotHoldings 
      join ccHolding in ccHoldList 
       on new { correct.ClientNo, correct.Depot, 
         correct.StockCode, correct.QuantityHeld } 
       equals new { ccHolding.ClientNo, ccHolding.Depot, 
          ccHolding.StockCode, ccHolding.QuantityHeld } 
      // TODO: Fill in the properties here based on correct and ccHolding 
      select new StocksHeldInCustody { ... }; 
var reportList = query.ToList(); 
+0

Hola, estoy recibiendo errores en la palabra clave "igual" y "ccHolding", ¿tendría que declarar esto como una variable antes de usarlo? –

+0

@DavidJohnson: Vaya, olvidé la parte "adentro". Vea mi edición, y si es nuevo en LINQ, me gustaría dedicar un tiempo a aprenderlo completamente. –

+0

Gracias, lo estoy intentando, pero parece como si hubiera sido inventado al azar sin patrón, supongo que es solo un caso de aprender aprender. Gracias de nuevo. –

3

Se podía mover los datos de la lista de búsqueda en un diccionario, con la clave de ser un hash único de los 3 elementos que están consultando. Entonces tendrá búsquedas muy rápidas y ahorrará millones de iteraciones.

3

comprobar mi post completo: Linq Join on Mutiple columns using Anonymous type

Hacer uso de LINQ combinación interna que va a hacer el trabajo para usted.

var list = (from x in entity 
      join y in entity2 
      on new { x.field1, x.field2 } 
     equals new { y.field1, y.field2 } 
     select new entity { fields to select}).ToList(); 

Ingreso de LINQ en múltiples campos

enter image description here

EmployeeDataContext edb= new EmployeeDataContext(); 
var cust = from c in edb.Customers 
      join d in edb.Distributors on 
      new { CityID = c.CityId, StateID = c.StateId, CountryID = c.CountryId, 
        Id = c.DistributorId } 
      equals 
      new { CityID = d.CityId, StateID = d.StateId, CountryID = d.CountryId, 
        Id = d.DistributorId } 
      select c; 
+0

Esa sintaxis de unión no es válida. Vea mi respuesta para un ejemplo correcto. –

+1

@JonSkeet - recién actualizado ....... gracias señor –

1

uso de LINQ para unirse a las listas y volver a nuestro gusto.

por ejemplo

var list1 = GetMassiveList(); 
var list2 = GetMassiveList(); 

var list3 = from a in list1 
      join b in list2 
       on new { a.Prop1, a.Prop2 } equals 
        new { b.Prop1, b.Prop2 } 
      select new { a.Prop1, b.Prop2 }; 

Para hacer su Outter unirse, puede utilizar DefaultIfEmpty() Este ejemplo está fijando su parte derecha de la unión a un objeto predeterminado (con frecuencia nulo) para los casos en que una unión wasn hecho.

por ejemplo

from a in list1 
join b in list2 
    on new { a.Prop1, a.Prop2 } equals 
     new { b.Prop1, b.Prop2 } 
into outer 
from b in outer.DefaultIfEmpty() 
select new 
    Prop1 = a.Prop1, 
    Prop2 = b != null ? b.Prop2 : "Value for Prop2 if the b join is null" 
}