Tech Off Thread

7 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

How To Modify An Element in the Dictionary Class?

Back to Forum: Tech Off
  • User profile image
    complete

    How To Modify An Element in the Dictionary Class? =======================================

    C# has this cool Dictionary class that you can use like a Hash Table.  Is there a way of changing the value of an indexed element without resorting to removing it like this?

                   int value = runningcount[city];
                    runningcount.Remove(city);
                    runningcount.Add(city, ++value);

  • User profile image
    JPeless

    Yes, just do

    2
    3
    int value = runningcount[city];
    runningcount[ city ] = ++value;
  • User profile image
    evildictait​or

    Dictionary<Foo, Bar> foobar = new Dictionary<Foo, Bar>();

    var foo = new Foo();

    var bar = new Bar();
    var bar2 = new Bar();

    foobar[foo] = bar; // invalid - foo isn't in the collection yet.

    foobar.Add(foo, bar); // correct way to add an element to the collection.

    foobar[foo] = bar2; // valid way of changing the element whose key is foo, but only once the element has been added in the first place.

    foobar.Remove(foo); // remove the item.

    Assert(foobar.Count == 0);

  • User profile image
    wkempf

    , evildictait​or wrote

    foobar[foo] = bar; // invalid - foo isn't in the collection yet.

    Incorrect. This is perfectly valid.

    , evildictait​or wrote

    foobar[foo] = bar2; // valid way of changing the element whose key is foo, but only once the element has been added in the first place.

    Again, incorrect. The key doesn't have to be present in the dictionary for assignment to work. JPeless had it correct, though either of the following are even simpler:

    runningcount[city] += 1;runningcount[city]++;

    Note, however, that these variants do require the key to be in the dictionary.

     

  • User profile image
    felix9

    Note, you should be really carefull about value types here, for example, this code get it wrong:

                var dict = new Dictionary<int, System.Windows.Point>();
                dict[1] = new System.Windows.Point(10, 10);
                Console.WriteLine(dict[1].ToString()); // outputs 10,10
                dict[1].Offset(10, 10); // modifying a COPY, the one in the dictionary is not changed
                Console.WriteLine(dict[1].ToString()); // still outputs 10,10
    

  • User profile image
    evildictait​or

    @wkempf: Heh. Turns out I should check before posting.

    I could've sworn that this behaviour wasn't the case at some point in the past :/

  • User profile image
    Sven Groot

    @wkempf: Another interesting thing to note is that this version, even if you do it in a single statement like you did, require two lookups into the dictionary: one to find the old value, and one to put the new one in. If profiling shows that this is a performance-sensitive part of your application, it can be worth it to use a reference type so you can modify the value without performing the second lookup.

    class Count
    {
        public int Value { get; set; }
    }
    
    Dictionary<string, Count> runningCount = new Dictionary<string, Count>();
    
    string key = "foo";
    Count count;
    if( runningCount.TryGetValue(key, out count) )
        count.Value++;
    else
        runningCount.Add(key, new Count() { Value = 1 });

    Note that this still performs a double lookup for values that aren't in the Dictionary, but that's unavoidable (ConcurrentDictionary provides a GetOrAdd method that provides this operation, but more for synchronizing this kind of operation than to avoid the extra lookup; ConcurrentDictionary is probably not the best idea to use if you don't actually need concurrency because of the overhead it adds to be thread-safe).

    And as always, profile your code both before and after you make a change like this because there's no point adding unnecessary complexity if this isn't a major performance bottleneck of your code.

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.