字典:属性或索引器无法分配:它是只读的。

7

我正在尝试按照以下方式更改字典中键的值:

//This part loads the data in the iterator
List<Recommendations> iterator = LoadBooks().ToList();
//This part adds the data to a list 
List<Recommendations> list = new List<Recommendations>();

        foreach (var item in iterator.Take(100))
        {
            list.Add(item);
        }
        //This part adds Key and List as key pair value to the Dictionary
        if (!SuggestedDictionary.ContainsKey(bkName))
        {
            SuggestedDictionary.Add(bkName, list);

        }
       //This part loops over the dictionary contents 
  for (int i = 0; i < 10; i++)
        {
            foreach (var entry in SuggestedDictionary)
            {
                rec.Add(new Recommendations() { bookName = entry.Key, Rate = CalculateScore(bkName, entry.Key) });
                entry.Key = entry.Value[i];
            }

        }

但是代码提示说"属性或索引器 KeyValuePair>.Key 无法赋值,因为它是只读的。" 我想要做的是在这里更改字典 Key 的值并将其分配给另一个值。

你到底想做什么?提供一些输入数据和期望的输出数据可能会有所帮助。(请参见https://stackoverflow.com/help/mcve) - dtanabe
为什么需要字典?从你的代码看,似乎只需要一个列表。 - TheGeneral
我正在尝试计算Pearson相关系数,它需要一个KeyValuePair来比较内容。这就是为什么我正在使用字典。@dtanabe请检查编辑后的代码。 - Muhammad Shahid
SuggestedDictionary 的类型参数是什么? - dtanabe
@dtanabe 这是一个Dictionary<string, List<Tentity>>类型的字典。 - Muhammad Shahid
你怎么可能将一个 Tentity 赋值给一个 string 呢?或者实际上是 Dictionary<string, List<string>> 吗?如果你想要将现有的键值映射重新关联到一个新的键上,那么 @TheGeneral 发布的答案是准确的。 - dtanabe
1个回答

12
唯一的方法是删除并重新添加字典项。
为什么呢?因为字典使用链式和桶式处理(类似于哈希表但具有不同的冲突解决策略)。

enter image description here

当向字典中添加一个元素时,它会被添加到与其键哈希值相对应的桶中。如果该桶中已经有了一个实例,则该实例会被添加到链表的前面。如果你想要更改键,那么它需要重新计算其所属的位置。因此,最简单和最明智的解决方案是删除并重新添加该项。 解决方案
var data = SomeFunkyDictionary[key];
SomeFunkyDictionary.Remove(key);
SomeFunkyDictionary.Add(newKey,data);

或者将其制作为扩展方法

public static class Extensions
{
   public static void ReplaceKey<T, U>(this Dictionary<T, U> source, T key, T newKey)
   {
      if(!source.TryGetValue(key, out var value))
         throw new ArgumentException("Key does not exist", nameof(key));
      source.Remove(key);
      source.Add(newKey, value);
   }
}

使用方法

SomeFunkyDictionary.ReplaceKey(oldKye,newKey);

顺带一提:向字典中添加和删除元素会产生惩罚;如果您不需要快速查找,最好根本不使用字典或使用其他策略。


1
非常好的且富有说明性的答案 +1 - RoadRunner
我已经尝试了上面的代码,但它显示集合已被修改,因此枚举操作可能无法执行。 - Muhammad Shahid
2
这是因为你在foreach循环内修改了字典。如果你想要在没有异常的情况下处理它,可以尝试将所有键取出并处理。"var keys = SuggestedDictionary.Keys; foreach (var key in keys) { DoSomething(SuggestedDictionary[key]); }" - Ondřej Kubíček

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