快速大规模更新字典
本文关键字:字典 更新 大规模 | 更新日期: 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.
}
这个场景将需要Add
和Remove
的多个版本允许更改具有相同值的所有键,仅将集合中的一个键更改为新值,删除具有相同值的所有键并从值集中仅删除一个键。在需要的时候为这些场景编写代码应该不难。
您需要生成一个新字典:
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,只要键没有改变