Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary: Property or indexer cannot be assigned to: it is read only

I am trying to change the value of Keys in my dictionary as follows:

//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];
            }

        }

But it says "Property or Indexer KeyValuePair>.Key Cannot be assigned to. Is read only. What I exactly want to do is change the value of dictionary Key here and assign it another value.

like image 841
Muhammad Shahid Avatar asked Jan 02 '23 09:01

Muhammad Shahid


1 Answers

The only way to do this will be to remove and re-add the dictionary item.

Why? It's because a dictionary works on a process called chaining and buckets (it's similar to a hash table with different collision resolution strategy).

enter image description here

When an item is added to a dictionary, it is added to the bucket that its key hashes to and, if there's already an instance there, it's prepended to a chained list. If you were to change the key, it will need to to go through the process of working out where it belongs. So the easiest and most sane solution is to just remove and re-add the item.

Solution

var data = SomeFunkyDictionary[key];
SomeFunkyDictionary.Remove(key);
SomeFunkyDictionary.Add(newKey,data);

Or make your self an extension method

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);
   }
}

Usage

SomeFunkyDictionary.ReplaceKey(oldKye,newKey);

Side Note : Adding and removing from a dictionary incurs a penalty; if you don't need fast lookups, it may just be more suitable not use a dictionary at all, or use some other strategy.

like image 100
TheGeneral Avatar answered Jan 13 '23 11:01

TheGeneral