字典中的循环

3
我使用这个:
foreach(KeyValuePair<String,String> entry in MyDic)
  {
      // do something with entry.Value or entry.Key

  }

问题在于我无法更改entry.Value或entry.Key的值。
我的问题是,当遍历字典时如何更改值或键?另外,字典是否允许重复的键?如果是,我们该如何避免呢? 谢谢。
5个回答

7
你不能在遍历字典项时更改字典项的值,但是如果值是引用类型的实例,则可以修改其属性。

例如,

public class MyClass 
{
    public int SomeNumber { get; set;}
}

foreach(KeyValuePair<string, MyClass> entry in myDict)
{
    entry.Value.SomeNumber = 3; // is okay
    myDict[entry.Key] = new MyClass(); // is not okay
}

尝试在循环遍历元素时修改字典(或任何集合)将导致InvalidOperationException,提示该集合已被修改。
回答您的具体问题,

我的问题是,在循环遍历字典时如何更改值或键?

两者方法基本相同。您可以像Anthony Pengram在他的答案中所说的那样遍历字典的副本,或者您可以首先遍历所有项以找出需要修改的项,然后再次遍历这些项的列表:
List<string> keysToChange = new List<string>();
foreach(KeyValuePair<string, string> entry in myDict)
{
    if(...) // some check to see if it's an item you want to act on
    {
        keysToChange.Add(entry.Key);
    }
}

foreach(string key in keysToChange)
{
   myDict[key] = "new value";

   // or "rename" a key
   myDict["new key"] = myDict[key];
   myDict.Remove(key);
}

那么,字典允许重复的键吗?如果是的话,我们该如何避免?

字典不允许有重复的键。如果您需要一个能够包含重复键的 <string, string> 键值对集合,请查看 NameValueCollection


一个迭代器可以解决这个问题吗?比如,在Java中的Map迭代器? - Xitrum
如果我没记错的话,foreach在幕后调用了一个迭代器,并且假设集合保持不变。这里有一个解释:https://dev59.com/l2855IYBdhLWcg3wGQTY。Anthony的答案可以工作,因为它创建了一个字典的副本,您可以对其进行迭代,然后修改原始集合。 - Adam Lear

6

在循环中更新字典将是一个问题,因为你不能在枚举字典时修改它。然而,你可以通过将字典转换为 KeyValuePair<> 对象的列表来轻松解决这个问题。你可以枚举该列表,然后就可以修改字典了。

foreach (var pair in dictionary.ToList())
{
    // to update the value
    dictionary[pair.Key] = "Some New Value";

    // or to change the key => remove it and add something new
    dictionary.Remove(pair.Key);
    dictionary.Add("Some New Key", pair.Value);
}

对于第二部分来说,字典中的关键字必须是唯一的。


1
@user,你的评论“为什么我看不到ToList()”-> 这是Linq的一部分,它在C# 3+中可用。如果您正在使用这样的版本,您可以将using System.Linq;语句添加到您的代码文件中(还假定您的项目引用了System.Core.dll,在新项目中默认引用)。 - Anthony Pegram

0

KeyValuePair的Key和value是只读的。但是你可以像这样更改一个value:

dictionary[key].Value = newValue;

但是如果你想改变键,你必须删除/添加一个键。

而且,字典不允许重复的键,否则会抛出ArgumentException异常。


但如果我的键是字符串?那么如何遍历字典? - Xitrum

0

在枚举键时,您不能修改它们。

我用于在枚举集合时进行更改的一种方法是,在找到匹配项并修改项时,使用break;退出foreach循环,并重新开始整个枚举。这是一种处理方式...

不,字典不能有重复的键。如果您想要按键排序并允许重复项的内容,应该使用其他数据结构。


-2

你可以这样做

for (int i = 0; i < MyDic.Count; i++)
{
    KeyValuePair<string, string> s = MyDic.ElementAt(i);
    MyDic.Remove(s.Key);
    MyDic.Add(s.Key, "NewValue");
}

而且字典不允许重复项


根据底层实现,当枚举集合时修改集合可能会产生不良结果... - jjxtra
1
@Anuraj 这将引发一个 InvalidOperationException 异常。 - Adam Lear
@Anuraj 不幸的是,这也可能会带来问题。字典中元素的顺序不被保证,因此当你添加新元素时,取决于它们最终的“索引”,你要么会在不应该处理它们时再次处理它们,要么在应该处理它们时不处理它们。 - Adam Lear

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接