.net-从c#词典中删除多个与谓词匹配的项的最佳方法?

我需要从字典中删除多个项目。一个简单的方法如下:

  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块中的项目的原因是,这将引发异常(“集合已修改...”)

我想做以下事情:

 MyCollection.RemoveAll(x =>x.Member==foo)

但是Dictionary <>类不会像List <>类那样公开RemoveRemoveAll(Predicate <> Match)方法。

做到这一点的最佳方法是什么(无论是明智的表现还是优雅的表现)?

Brann asked 2020-01-18T02:41:15Z
6个解决方案
86 votes

这是另一种方法

foreach ( var s in MyCollection.Where(kv => kv.Value.Member == foo).ToList() ) {
  MyCollection.Remove(s.Key);
}

直接将代码推送到列表中可以避免“枚举时删除”问题。 .ToList()将在foreach真正开始之前强制进行枚举。

JaredPar answered 2020-01-18T02:41:44Z
21 votes

您可以创建扩展方法:

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);
aku answered 2020-01-18T02:42:04Z
11 votes

而不是删除,只是做逆。 从仅包含您感兴趣的元素的旧字典创建新字典。

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);
}
Amy B answered 2020-01-18T02:42:24Z
10 votes

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);
Jerome answered 2020-01-18T02:42:45Z
0 votes

您可以只更改循环以使用索引(即FOR而不是FOREACH)吗? 当然,您必须向后循环,即将count-1减少到零。

Geoff answered 2020-01-18T02:43:05Z
0 votes

而不是仅仅进行逆运算(从仅包含您感兴趣的元素的旧字典中创建一个新字典),然后让垃圾收集器处理旧字典:

var newDictionary = oldDictionary.Where(x => x.Value != foo);
Darin Dimitrov answered 2020-01-18T02:43:25Z
translate from https://stackoverflow.com:/questions/469202/best-way-to-remove-multiple-items-matching-a-predicate-from-a-c-sharp-dictionary