C# 快速批量更新字典

C# 快速批量更新字典,c#,dictionary,C#,Dictionary,我有一个字典,希望根据当前值一次性更新某些元素,例如,将值为10的所有元素更改为值为14或其他 我以为这对LINQ/lambda的东西来说很容易,但它并不像我想象的那么简单。我目前的做法是: List<KeyValuePair<int, int>> kvps = dictionary.Where(d => d.Value == oldValue).ToList(); foreach (KeyValuePair<int, int> kvp in kvps)

我有一个
字典
,希望根据当前值一次性更新某些元素,例如,将值为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;
}
List kvps=dictionary.Where(d=>d.Value==oldValue.ToList();
foreach(kvps中的KeyValuePair kvp)
{
字典[KeyValuePair.Key]=newValue;
}

问题是
dictionary
相当大(数十万个元素),我在循环中运行了数千次这段代码,所以速度非常慢。必须有更好的方法…

您需要生成新词典:


<代码> d=D-字典(W= > WKY,W==10=14:W.value)

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

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

公共类SharedValueDictionary:IDictionary { 私有列表值; 私钥; //现在,当您添加一个新的键/值对时,实际上 //查看values集合,查看该值是否已存在 //存在。如果存在,则向指向该现有对象的键添加一个条目 //否则,您将创建一个新的MyValueObject来包装该值并向其中添加条目 //两个系列。 }
此场景需要多个版本的
Add
Remove
,以允许更改具有相同值的所有键、仅将集合中的一个键更改为新值、删除具有相同值的所有键以及仅从值集中删除一个键。在需要时为这些场景编写代码并不困难。

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

我认为每个人都缺少的一点是,它非常琐碎:

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

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

在编辑之后,这似乎是一个立即的改进:

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


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

如果你生成一个新字典怎么办?@john:那么它会更慢。好主意;不幸的是,它似乎运行得更慢了。@Andrew Arnold-请记住它是一个lambda:),您的for循环可能是我能想到的快速和肮脏的唯一选择。或者考虑Jeff Yates提出的问题。它不能解决O.P.所面临的问题,因为在引擎盖下,字典将循环遍历这些元素,并将键值对一个接一个地添加到新对象上。@保罗·桑托斯-我明白,因此我的评论。这种方法的问题是,如果一个键值对需要更新,而另一个键值对具有相同值,则不需要更新怎么办?@Paulo Santos-如果一个键值对发生更改,另一个键值对将自动更改。我理解Jeff建议的方法,但问题仍然存在。假设我们有一对X:10和Y:10,例如,X需要更新到15,而不是Y。Jeff建议的集合将始终将X和Y都更改为相同的值。@Paulo:在这种情况下,您需要一种不同于“添加到集合”的方法,允许您指定所需的行为。这个可选的add将把键的目标转移到一个新的value对象,而不是改变它现有的value对象。在函数的开头,dictionary中的所有值都有不同的值,所以我认为这不会更有效。(也许这表明我对集合类型的选择不是最好的。)这会使按键查找速度变慢,不是吗?我认为这是我最初的方法,但效果不太好,可能是因为我使用的算法,所以我再试试。@Jeff:是的。如果这是相关的,你可以采取中间立场,把两者都用在一个类中。您可以使用这些集合来获取用于质量值更新的键,并且您可以正常使用字典,同时记住保持集合同步
ContainsKey
将查找字典中键为
oldValue
的所有元素;我想要值为
oldValue
的元素。是的,我很确定问题中的代码实际上没有反映我想说的内容。很抱歉,我只看了lambda谓词就错过了这一点-我已经尝试过了,但是你做不到。
属性是只读的。改变它的唯一方法是通过检查键。对,我刚刚通过在分析器中获取这一信息发现了这一点:)
if (dictionary.ContainsKey(oldValue))
   dictionary[key] = newValue;
foreach (var kvp in dictionary.Where(d => d.Value == oldValue))
{
   kvp.Value = newValue;
}