2010-03-17 14 views
6

tiene una propiedad: string Código y 10 otros.Cómo optimizar este código

códigos comunes es una lista de cadenas (string []) cars una lista de coches (Car []) filteredListOfCars is List.

for (int index = 0; index < cars.Length; index++) 
{ 
    Car car = cars[index]; 
    if (commonCodes.Contains(car.Code)) 
    { 
     filteredListOfCars.Add(car); 
    } 
} 

Desafortunadamente esta pieza de metodo tarda demasiado.

Tengo alrededor de 50k registros

¿Cómo puedo reducir el tiempo de ejecución ??

Respuesta

16

Jared ha señalado correctamente que puede optimizar esto con un HashSet, pero también me gustaría señalar que todo el método es innecesario, desperdiciando memoria para la lista de salida y haciendo que el código sea menos claro.

Se puede escribir el método entero como:

var commonCodesLookup = new HashSet<int>(commonCodes); 
var filteredCars = cars.Where(c => commonCodesLookup.Contains(c.Code)); 

ejecución de la operación filteredCars filtrado se diferirán, por lo que si el consumidor de que sólo quiere los primeros 10 elementos, es decir, mediante el uso de filteredCars.Take(10), entonces este no necesita construir la lista completa (o ninguna lista en absoluto).

+0

El método Linq Join hace la lógica de búsqueda para que usted no tenga que especifica el HashSet. cars.Join (commonCodes, car => car.Code, code => code, (car, code) => car) – DRBlaise

+0

@DRBlaise: Es cierto que 'Join' usa una tabla hash, pero también es un detalle de implementación , y es arriesgado confiar en tales cosas ya que están sujetas a cambios (incluso si el cambio es improbable). Si desea garantizar un cierto nivel de rendimiento, debe ser explícito sobre la semántica. – Aaronaught

+0

¿Por qué int? nuevo Hash no es correcto? – user278618

20

La optimización más fácil es convertir los códigos comunes de string[] a una estructura de búsqueda más rápida como Dictionary<string,object> o HashSet<string> si está utilizando .Net 3.5 o superior. Esto reducirá la gran complejidad de O de este ciclo y, dependiendo del tamaño de CommonCodes, debería hacer que este ciclo se ejecute más rápido.

+0

+1 por darme vuelta por 30 segundos; p – Jake

0

podría utilizar los LINQ unen comando, como

var filteredListOfCars = cars.Join(commonCodes, c => c.Code, cC => cC, (car, code) => car).ToArray(); 
0

Aquí hay una alternativa a las opciones de LINQ (que también son buenas ideas): Si usted está tratando de hacer el filtrado rápido, sugeriría aprovechando de tipos incorporados. Puede crear un DataTable que tenga dos campos, la identificación del automóvil en su matriz y el código (puede agregar las otras 10 cosas si también importan). Luego puede crear un DataView a su alrededor y usar la propiedad de filtro de eso. Utiliza una indexación muy rápida internamente (creo que B-trees), por lo que probablemente no puedas superar su rendimiento manualmente a menos que seas un genio de los algoritmos, que si lo fueras, no estarías preguntando aquí. Depende de lo que estés haciendo y de cuánto sea importante el rendimiento.

1

Para hacer lo que quiera, usaría el método Linq ToLookup para crear un ILookup en lugar de usar un diccionario. ToLookup fue creado especialmente para este tipo de escenario. Básicamente es una búsqueda indexada en grupos. Desea agrupar sus autos por Code.

var carCodeLookup = cars.ToLookup(car => car.Code); 

La creación de la carCodeLookup sería lento pero luego se puede utilizar para la búsqueda rápida de coches basados ​​en Code. Para obtener su lista de autos que están en su lista de códigos comunes, puede hacer una búsqueda rápida.

var filteredCarsQuery = commonCodes.SelectMany(code => carCodeLookup[code]); 

Esto supone que la lista de los coches no cambia muy a menudo y es su commonCodes que son dinámicos entre consultas.

0

Parece que lo que realmente está comprobando es si el "código" es común, no el automóvil. Podría considerar un patrón de peso de mosca, donde los automóviles comparten instancias comunes de objetos de código. El objeto de código puede tener una propiedad IsCommon y una propiedad Value. Luego puede hacer algo al efecto de actualizar los objetos de código usados ​​siempre que cambie la lista de códigos comunes. Ahora cuando filtre, solo necesita verificar la propiedad IsCommon de cada código de auto