快速批量更新词典

时间:2011-04-14 19:15:44

标签: c# dictionary

我有一个Dictionary<int, int>,并希望根据其当前值一次更新某些元素,例如将值为10的所有元素更改为值为14或其他值。

我想象一下这对于一些LINQ / lambda来说很容易,但它看起来并不像我想象的那么简单。我目前的做法是:

List<KeyValuePair<int, int>> kvps = dictionary.Where(d => d.Value == oldValue).ToList();
foreach (KeyValuePair<int, int> kvp in kvps)
{
   dictionary[KeyValuePair.Key] = newValue;
}

问题是dictionary非常大(成千上万的元素)而且我在循环中运行这些代码数千次,所以速度非常慢。必须有更好的方法......

5 个答案:

答案 0 :(得分:6)

这可能是错误的数据结构。您试图根据它们的值查找字典条目,这与通常的模式相反。也许你可以存储当前映射到某些值的键集。然后你可以快速移动这些集,而不是分别更新每个条目。

答案 1 :(得分:2)

我会考虑编写自己的集合类型来实现这一点,即具有相同值的键实际上共享相同的值实例,以便在一个位置更改它会更改所有键。

类似于以下内容(显然,此处省略了大量代码 - 仅用于说明目的):

public class SharedValueDictionary : IDictionary<int, int>
{
   private List<MyValueObject> values;

   private Dictionary<int, MyValueObject> keys;

   // Now, when you add a new key/value pair, you actually
   // look in the values collection to see if that value already
   // exists. If it does, you add an entry to keys that points to that existing object
   // otherwise you create a new MyValueObject to wrap the value and add entries to
   // both collections.
}

此方案需要多个版本的AddRemove才能更改具有相同值的所有键,只将一个键的一个键更改为新值,删除所有键相同的值,只从值集中删除一个键。在需要时为这些场景编码应该不难。

答案 2 :(得分:0)

您需要生成一个新词典:

d = d.ToDictionary(w => w.Key, w => w.Value == 10 ? 14 : w.Value)

答案 3 :(得分:0)

我认为每个人都必须缺少的是它非常微不足道:

List<int> keys = dictionary.Keys.Where(d => d == oldValue);

NOT 按值查找密钥(正如其他人提供的那样)。 相反,keys.SingleOrDefault()现在将按照定义返回等于oldValue的单个密钥(如果它存在于字典中)。所以整个代码应简化为

if (dictionary.ContainsKey(oldValue))
   dictionary[key] = newValue;

这很快。现在我有点担心这可能确实是OP的意图,但它他写的东西。因此,如果现有代码能够满足他的需求,他现在将拥有相同的高性能版本:)

答案 4 :(得分:0)

编辑后,这似乎立即得到改善:

foreach (var kvp in dictionary.Where(d => d.Value == oldValue))
{
   kvp.Value = newValue;
}

我很确定你可以直接更新kvp,只要密钥没有改变