Bra*_*ann 51 .net c# linq collections dictionary
我需要从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);
Run Code Online (Sandbox Code Playgroud)
我无法直接删除foreach块中的项目的原因是这会抛出异常("Collection was modified ...")
我想做以下事情:
MyCollection.RemoveAll(x =>x.Member==foo)
Run Code Online (Sandbox Code Playgroud)
但是Dictionary <>类没有公开RemoveAll(Predicate <> Match)方法,就像List <> Class那样.
这样做的最佳方式(性能明智和优雅明智)是什么?
Jar*_*Par 86
这是另一种方式
foreach ( var s in MyCollection.Where(kv => kv.Value.Member == foo).ToList() ) {
MyCollection.Remove(s.Key);
}
Run Code Online (Sandbox Code Playgroud)
直接将代码推送到列表中可以避免"在枚举时删除"问题.在.ToList()
将迫使枚举真正开始在foreach之前.
aku*_*aku 21
你可以创建一个扩展方法:
public static class DictionaryExtensions
{
public static void RemoveAll<TKey, TValue>(this IDictionary<TKey, TValue> dict,
Func<TValue, bool> predicate)
{
var keys = dict.Keys.Where(k => predicate(dict[k])).ToList();
foreach (var key in keys)
{
dict.Remove(key);
}
}
}
...
dictionary.RemoveAll(x => x.Member == foo);
Run Code Online (Sandbox Code Playgroud)
Amy*_*y B 11
而不是删除,只是做反过来.从旧的字典创建一个只包含您感兴趣的元素的字典.
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);
}
Run Code Online (Sandbox Code Playgroud)
Jer*_*ome 10
修改版Aku的扩展方法解决方案.主要区别在于它允许谓词使用字典键.一个细微的差别是它扩展了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);
Run Code Online (Sandbox Code Playgroud)
从 .NET 3.0 开始,现在允许从Dictionary<TKey,TValue>
枚举它的同时删除项目。根据文档:
仅限 .NET Core 3.0+:唯一不会使枚举器无效的变异方法是
Remove
和Clear
。
以下是提议并批准此更改的 GitHub 问题:允许字典<K,V>.在枚举期间删除
所以RemoveAll
扩展方法可以简单地实现如下:
/// <remarks>.NET Core 3.0+ only.</remarks>
public static void RemoveAll<TKey, TValue>(this Dictionary<TKey, TValue> source,
Predicate<KeyValuePair<TKey, TValue>> predicate)
{
foreach (var pair in source)
if (predicate(pair))
source.Remove(pair.Key);
}
Run Code Online (Sandbox Code Playgroud)
使用示例:
myDictionary.RemoveAll(e => e.Value.Member == foo);
Run Code Online (Sandbox Code Playgroud)