2009-05-06 9 views
5

Tengo un diccionario y una lista de claves para eliminar del diccionario. Esta es mi implementación en este momento:¿Cómo puedo usar LINQ para "podar" un diccionario?

var keys = (from entry in etimes 
      where Convert.ToInt64(entry.Value) < Convert.ToInt64(stime) 
      select entry.Key).ToList(); 

foreach (var key in keys) 
{ 
    etimes.Remove(key); 
    count--; 
} 

¿Hay algo que pueda hacer para eliminar el bucle foreach?

+1

Por cierto que no necesitabas .ToList() foreach funcionará con cualquier IEnumerable –

+0

LINQ es un lenguaje de consulta, que puede crear nuevos datos mediante la transformación de datos existentes. No puede cambiar los datos existentes. – codymanix

Respuesta

6
var pruned = etimes.Where(entry => Convert.ToInt64(entry.Value) >= 
    Convert.ToInt64(stime)).ToDictionary(entry => entry.Key, 
     entry => entry.Value); 

Esta declaración simplemente filtra el diccionario utilizando la función de LINQ Where para seleccionar los elementos que mantienen a en lugar de los de quitar (que a su vez requiere más código, como se mostró). El ToDictionary convierte thwe IEnumerable<KeyValuePair<TKey, TValue>> al tipo deseado Dictionary<TKey, TValue>, y es al menos bastante simple, si no terriblemente elegante o eficiente debido a la necesidad de especificar las dos expresiones lambda para seleccionar la clave y el valor de KeyValuePair (y luego crear un nuevo diccionario) Al decir esto, realmente no lo veo como un problema, especialmente si el diccionario es pequeño y/o el número de elementos que se eliminan es grande.

+0

No me gustaría hacer ningún comentario sobre el rendimiento por cierto, si te importa eso, prueba los dos métodos. No estoy seguro de que su solución original con foreach sea * mucho * más rápida. – Noldorin

+0

No me preocupa el rendimiento, solo hay unas pocas teclas en el diccionario en cualquier momento. Solo estoy tratando de obtener un mejor manejo de LINQ. Gracias, esto funcionó muy bien. – scottm

+0

Esto puede ser mucho más caro que el simple para cada bucle porque creará un nuevo diccionario. Y creo que tampoco mejora la legibilidad. Así que solo me quedaré con el para cada bucle y tal vez moverlo a un método (de extensión), pero no veo ninguna ganancia para la solución LINQ. –

0

Bueno, problemas de rendimiento o de legibilidad a un lado, no podría esto también puede hacer algo como lo siguiente:

<Extension> void itemDelete(List l, object item) { 
    l.Remove(item) 
} 

var keys = (from entry in etimes 
     where Convert.ToInt64(entry.Value) < Convert.ToInt64(stime) 
     select entry.Key).ToList(); 

keys.foreach(itemDelete()); 

perdona mis codificación, no estoy 100% seguro de la sintaxis exacta (sobre todo en C#); considera ese pseudo-código. Observe la adición de la nueva función y la función .foreach al final de la consulta LINQ. Sé que esto sería posible en VB, supongo que C# tiene algo similar ... si no, siempre puedes escribir tu propia extensión .foreach. Puede o no mejorar algo, pero es una idea.

+0

Perdóname si esta es una pregunta tonta, pero ¿crearías este método de extensión en una clase parcial? Todavía estoy tratando de comprender los métodos de extensión y cómo puedes usarlos y crearlos. – Jagd

+0

@Jagd: esta no es razón alguna para usar una clase parcial. La práctica recomendada es declararlos por sí solos dentro de una * clase estática * y métodos de extensión de grupo en clases estáticas de funcionalidades similares. – Noldorin

+0

En VB los creas en Módulos, así que ... Diría que escuchas las Mejores prácticas de Noldorin. – eidylon

Cuestiones relacionadas