2010-12-01 16 views
5

Tengo una tarea simple en la que necesito verificar objetos en un diccionario y si se cumplen ciertos criterios, se pasa a otro. Lo que estoy preguntando es si hay algún patrón bueno en el que pueda usar la función de idioma para lograrlo. El enfoque directo es simple: use la recopilación temporal, el primer paso determine los candidos, el segundo paso haga el movimiento real. Está bien, pero no es genial.¿Cómo mover objetos entre diccionarios?

código actual

class Order 
{ 
    public int ID; 
    public bool IsReady; 
} 

Dictionary<int, Order> ActiveDictionary; 
Dictionary<int, Order> ProcessedDictionary; 

public Update() 
{  
// temporary list, uncool 
List<Order> processed = new List<Order>(); 


// fist step 
foreach(Order ord in ActiveDictionary) 
{ 
    if(ord.IsReady) 
    { 
    processed.Add(ord); 
    } 
} 

// ok now lets move 
foreach(Order ord in processed) 
{ 
    ActiveDictionary.Remove(ord.ID); 
    ProcessedDictionary.Add(ord.ID, ord); 
} 
} 

Respuesta

7

No hay nada realmente mal con el código que tiene.

Como ejercicio de las alternativas, se podría hacer algo como ...

ProcessedDictionary = ProcessedDictionary 
    .Concat(
     ActiveDictionary.Where(kvp => kvp.Value.Ready) 
    ) 
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); 

ActiveDictionary = ActiveDictionary.Where(kvp => !kvp.Value.Ready) 
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); 
+0

Tengo una sintiendo que realmente quieres usar 'Where' y no' Select'. Dudo que el código se compile como está ahora, ya que la entrada a 'ToDictionary' es probablemente un valor' bool'. –

+0

@Fredrik ha! tienes razón, día largo :) –

+0

... y está mi voto :) –

3

si la respuesta Rex M 's no es adecuado (tal vez usted no desea reconstruir Diccionarios en cada iteartion) , entonces como pequeña mejora que puedo sugerir para reemplazar

// temporary list, uncool 
List<Order> processed = new List<Order>(); 

// fist step 
foreach(Order ord in ActiveDictionary) 
{ 
    if(ord.IsReady) 
    { 
    processed.Add(ord); 
    } 
} 

a

var processed = ActiveDictionary.Where(x=>x.Value.Ready).ToArray(); 

y el resto de su código sería

foreach(var item in processed) 
{ 
    ActiveDictionary.Remove(item.Key); 
    ProcessedDictionary.Add(item.Key, item.Value); 
} 

UPD: Como Ani comentado, no hay otra solución por igual:

var processed = ActiveDictionary.Values.Where(x=>x.Ready).ToArray(); 

foreach(var item in processed) 
{ 
    ActiveDictionary.Remove(item); 
    ProcessedDictionary.Add(item.Id, item); 
} 
+0

Me gusta esta respuesta porque la intención del código es bastante clara al leerlo: "Buscar todos los elementos como este y eliminarlos/agregarlos de los diccionarios" – mlibby

+0

Me gusta mucho LINQ. Pero a veces simplemente no es el lugar adecuado.Esta es la respuesta: el estilo antiguo y bueno con una mezcla pequeña de LINQ es mucho más legible y de estilo completamente LINQ. –

1

probar esto

var keys = ActiveDictionary 
    .Where(kv => kv.Value.Ready) 
    .Select(kv => kv.Key).ToList(); 
keys.ForEach(k => 
     { 
      ProcessedDictionary.Add(k, ActiveDictionary[k]); 
      ActiveDictionary.Remove(k); 
     }); 
+0

Si no lo hace. Seleccione (kv => kv.Key), entonces no necesitará buscar valor en ActiveDictionary (cuando agrega elementos en Foreach). –

Cuestiones relacionadas