collection - map dictionary c#
¿La mejor forma de eliminar elementos múltiples que coincidan con un predicado de ac#Dictionary? (6)
Necesito eliminar varios elementos de un diccionario. Una forma simple de hacerlo es la siguiente:
List<string> keystoremove= new List<string>();
foreach (KeyValuePair<string,object> k in MyCollection)
if (k.Value.Member==foo)
keystoremove.Add(k.Key);
foreach (string s in keystoremove)
MyCollection.Remove(s);
El motivo por el que no puedo eliminar directamente los elementos en el bloque foreach es que arrojaría una Excepción ("La colección se modificó ...")
Me gustaría hacer lo siguiente:
MyCollection.RemoveAll(x =>x.Member==foo)
Pero la clase Dictionary <> no expone un método RemoveAll (Predicate <> Match), como lo hace la clase List <>.
¿Cuál es la mejor manera (tanto de rendimiento sabio como elegante) para hacer eso?
¿Puedes simplemente cambiar tu ciclo para usar un índice (es decir, FOR en lugar de FOREACH)? Tendría que hacer un ciclo hacia atrás, por supuesto, es decir, conteo-1 hasta cero.
Aquí hay una manera alternativa
foreach ( var s in MyCollection.Where(kv => kv.Value.Member == foo).ToList() ) {
MyCollection.Remove(s.Key);
}
Al insertar el código en una lista directamente, puede evitar el problema de "eliminación al enumerar". The .ToList()
forzará la enumeración antes de que el foreach realmente comience.
En lugar de eliminar, haga lo contrario (cree un nuevo diccionario a partir del anterior que contenga solo los elementos que le interesan) y deje que el recolector de basura se encargue del diccionario anterior:
var newDictionary = oldDictionary.Where(x => x.Value != foo);
En lugar de eliminar, solo haz lo contrario. Cree un nuevo diccionario a partir del anterior que contenga solo los elementos que le interesen.
public Dictionary<T, U> NewDictionaryFiltered<T, U>
(
Dictionary<T, U> source,
Func<T, U, bool> filter
)
{
return source
.Where(x => filter(x.Key, x.Value))
.ToDictionary(x => x.Key, x => x.Value);
}
Versión modificada de la solución del método de extensión de Aku. La principal diferencia es que permite que el predicado use la clave del diccionario. Una pequeña diferencia es que extiende IDictionary en lugar de Dictionary.
public static class DictionaryExtensions
{
public static void RemoveAll<TKey, TValue>(this IDictionary<TKey, TValue> dic,
Func<TKey, TValue, bool> predicate)
{
var keys = dic.Keys.Where(k => predicate(k, dic[k])).ToList();
foreach (var key in keys)
{
dic.Remove(key);
}
}
}
. . .
dictionary.RemoveAll((k,v) => v.Member == foo);
puedes crear un método de extensión :
public static class DictionaryExtensions
{
public static void RemoveAll<TKey, TValue>(this Dictionary<TKey, TValue> dic,
Func<TValue, bool> predicate)
{
var keys = dic.Keys.Where(k => predicate(dic[k])).ToList();
foreach (var key in keys)
{
dic.Remove(key);
}
}
}
...
dictionary.RemoveAll(x => x.Member == foo);