在 C# 的 for 循环中修改字典

Modify a dictionary in a for loop in C#

我在 C/C++ 方面经验丰富,但在 C# 方面几乎是个新手。我的问题很简单。假设我们有一个包含整数键和值的散列 table,我们希望将散列 table 中的所有值递增 1。我们更愿意使用 O(1) 额外内存来完成此操作。

下面是一个解决方案,在我看来,它有点丑陋。有没有其他方法让它看起来更像样?

        Dictionary<int, int> dict = new Dictionary<int, int>();
        for (int i = 0; i < dict.Count; ++i)
        {
            dict[dict.Keys.ElementAt(i)]++;
        } 

PS:听说foreach在C#中是只读的。但是,有没有像 C++ 中的 for(auto it& : dict) it.second++ 这样的方法,我仍然可以使用它在 C# 中完成这个任务?

为什么不允许这样做?尝试分配给它可能不会做你想做的事——它不会修改原始集合的内容。这是因为变量 x 不是对列表中元素的引用 - 它是一个副本。

因为 KeyValuePair 具有键和值的只读属性,所以要在 foreach 中执行此操作,您需要第二个 Dictionnary 来添加这些项并处理原始项

        Dictionary<int, int> dict = new Dictionary<int, int>();
        dict.Add(0, 1);
        dict.Add(1, 2);
        dict.Add(2, 3);

        Dictionary<int, int> dictOutput = new Dictionary<int, int>();
        foreach (KeyValuePair<int,int> item in dict)
        {
            dictOutput.Add(item.Key, item.Value + 1);
        }
        dict.Dispose();

Dictionary<,> 本身并没有提供这样做的好方法 - 因为更新与键关联的值算作使任何迭代器无效的更改。 ConcurrentDictionary<,> 允许这样做,甚至有一个 AddOrUpdate 方法可以帮助您:

using System;
using System.Linq;
using System.Collections.Concurrent;

class Test
{
    static void Main()
    {
        var dict = new ConcurrentDictionary<int, int>
        {
            [10] = 15,
            [20] = 5,
            [30] = 10
        };
        foreach (var key in dict.Keys)
        {
            dict.AddOrUpdate(key, 0, (k, v) => v + 1);
        }
        Console.WriteLine(string.Join("\r\n", dict.Select(kp => $"{kp.Key}={kp.Value}")));
    }
}

您可以在这种情况下使用 foreach,但我们需要以不使用字典的方式来执行此操作,因为更新它会更改内部迭代器(这就是 foreach 跟上它所在位置的方式)迭代时,请查看此 SO 以获取更多详细信息:) 在此实现中,我们将迭代键列表,然后在迭代时更新每个键的值。

 Dictionary<int, int> dict = new Dictionary<int, int>();
 foreach (var i in dict.Keys.ToList())
 {
     dict[i]++;
 }

Update 正如 Servy 指出的那样,我没有提到这个解决方案不是 O(1),而是 O(N)。

您的循环中不需要 dict.Keys.ElementAt(i) 索引。您可以将其视为一个数组。 Dictionarys 是 C# 等同于 C++ 中的 Map。您需要做的就是增加您的价值

for (int i = 0; i < dict.Count; i ++)
    dict[i]++;

此外,如果您使用的是 Dictionary<int, int>,则只需使用

int[] dict = new int[count];

反正你的键就是索引;但我真的只推荐使用 List<int>。这样您就可以动态调整大小,而无需做所有额外的工作。

这样,您可以像这样创建 List<int>

List<int> lstDict = new List<int>;
int value; /*assign to whatever value you need to insert*/
int count; /*however many elements you need*/

for (int i = 0; i < count; i ++) 
    lstDict.Add(value);

//
//  Whatever else you need to do
//

for (int i = 0; i < count; i ++)
    lstDict[i]++;

有很多方法可以完成您想要完成的事情。您可以使用这些选项中的任何一个来实现相同的目的。如果您想坚持使用 Dictionarys,只需使用我放在那里的第一个片段。我个人不会使用它们,除非我需要使用两种不同的数据类型,比如 Dictionary<string, int>