从ac#Dictionary中删除多个匹配谓词的项目的最佳方法?
我需要从字典中删除多个项目。 一个简单的方法如下:
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);
我不能直接删除foreach块中的项目的原因是,这将抛出一个exception(“集合被修改…”)
我想要做以下事情:
MyCollection.RemoveAll(x =>x.Member==foo)
但是Dictionary <>类不像List <> Class那样公开一个RemoveAll(Predicate <> Match)方法。
什么是最好的方式(既明智又明智)做到这一点?
这是另一种方式
foreach ( var s in MyCollection.Where(kv => kv.Value.Member == foo).ToList() ) { MyCollection.Remove(s.Key); }
直接将代码推入列表允许您避免“枚举时移除”问题。 .ToList()
将在foreach真正开始之前强制枚举。
你可以创build扩展方法 :
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);
而不是删除,只是做相反的事情。 从旧的只包含您感兴趣的元素创build一个新的字典。
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); }
Aku的扩展方法解决scheme的修改版本。 主要区别是它允许谓词使用字典键。 一个小的区别是它扩展了IDictionary而不是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);
你可以改变你的循环使用索引(即FOR而不是FOREACH)? 当然,你必须向后循环,也就是说,计数-1降到零。
而不是去除反过来(从旧的只包含你感兴趣的元素创build一个新的字典),让垃圾回收器照顾旧的字典:
var newDictionary = oldDictionary.Where(x => x.Value != foo);