快速大规模更新字典

本文关键字:字典 更新 大规模 | 更新日期: 2023-09-27 17:50:17

我有一个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非常大(成千上万的元素),我在循环中运行这段代码数千次,所以它非常慢。一定有更好的办法…

快速大规模更新字典

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

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

类似以下内容(显然,这里省略了大量代码—只是为了说明目的):

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的多个版本允许更改具有相同值的所有键,仅将集合中的一个键更改为新值,删除具有相同值的所有键并从值集中仅删除一个键。在需要的时候为这些场景编写代码应该不难。

您需要生成一个新字典:

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

我想每个人一定都忽略了一件事,那就是它是非常微不足道的:

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

不是按值查找键(就像其他人提供的那样)。相反,keys.SingleOrDefault()现在将根据定义返回等于oldValue的单个键,如果它存在于字典中。所以整个代码应该简化为

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

真快。现在我有点担心,这可能确实是不是是OP的意图,但它他写的。因此,如果现有的代码可以满足他的需要,他现在将拥有一个高性能的版本:)

编辑后,这似乎是一个立竿见影的改进:

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

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