Как обновить значение, хранящееся в словаре в C #?

455

Как обновить значение для конкретного ключа в словаре Dictionary<string, int>?

Amit
источник
У меня сложный тип хранится в виде значения в словаре. Когда я хочу изменить свойство сохраненного значения, я получаю CS1612. Поэтому я должен обойти: var v = dict [c]; v.dprop = c.sprop; dict [c] = v;
peter70

Ответы:

762

Просто укажите словарь на данный ключ и назначьте новое значение:

myDictionary[myKey] = myNewValue;
ccalboni
источник
Таким образом, этот простой метод, кажется, также является лучшей заменой хорошо известным методам ".Add" и ".TryGetValue" без необходимости изменять значение. (?) По крайней мере, если не имеет значения перезаписывать ключи, например, в ситуации, когда не исключено, что ключи записываются более одного раза в цикле. Или кто-то видит какие-то недостатки? Тем более, что .Add имеет ptifall для начинающих, что если if-wrapper или TryGetValue забыты, он может нормально работать в тестах, а с другими тестовыми данными, где .Add вызывается дважды для одного и того же ключа, он генерирует исключение.
Филм
1
Интересным моментом этой операции является то, что это UPSERT (ключ, значение) в словарь. блестящий!
Сорен
1
Как заявил Пини, это должен быть ответ на вопрос. Нужно правильно и изменить его.
Лев Гурдиан,
190

Это возможно путем доступа к ключу в качестве индекса

например:

Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary["test"] = 1;
dictionary["test"] += 1;
Console.WriteLine (dictionary["test"]); // will print 2
Amit
источник
11
Если в списке нет элемента «test», то list ["test"] = list ["test"] + 1; вызовет KeyNotFoundException! Чистое назначение несуществующего индексатора будет работать. list ["test"] = 1;
Стивен Спирка
Можете ли вы также использовать list ["test"] ++ ;?
aufty
17
не называйте список словаря, называйте его собаками, кошками или
диктом
1
@aufty вы можете написать ++dictionary["test"];или dictionary["test"]++;только в том случае, если в словаре есть запись со значением ключа «test» - пример: if(dictionary.ContainsKey("test")) ++dictionary["test"]; else dictionary["test"] = 1; // create entry with key "test"
gerryLowry
46

Вы можете следовать этому подходу:

void addOrUpdate(Dictionary<int, int> dic, int key, int newValue)
{
    int val;
    if (dic.TryGetValue(key, out val))
    {
        // yay, value exists!
        dic[key] = val + newValue;
    }
    else
    {
        // darn, lets add the value
        dic.Add(key, newValue);
    }
}

Преимущество, которое вы получаете, заключается в том, что вы проверяете и получаете значение соответствующего ключа всего за 1 доступ к словарю. Если вы используете ContainsKeyдля проверки существования и обновления значения с помощью, dic[key] = val + newValue;то вы получаете доступ к словарю дважды.

max_force
источник
4
Вместо dic.Add(key, newValue);вы можете использовать использование dic[key] = newvalue;.
Маке
Что произойдет, если вы сделаете «dic [key] = value», а «key» не существует?
суперпуччо
1
@superpuccio вы получаете KeyNotFoundException
ntroncos
8
@ntroncos не верно, он добавит этот ключ в словарь с указанным значением. + = не будет работать с несуществующим ключом, так как это просто синтаксический сахар для dic [key] = value + dic [key].
Lastas
2
Это должен быть ответ на вопрос, поскольку он касается обновления словаря, а не просто добавления к нему.
Одинокий кодер
15

Использовать LINQ: доступ к словарю для ключа и изменение значения

Dictionary<string, int> dict = new Dictionary<string, int>();
dict = dict.ToDictionary(kvp => kvp.Key, kvp => kvp.Value + 1);
INT_24h
источник
Я даже не понимаю, как это работает, но это удивительно
hexagonest
1
Создание другого словаря не имеет смысла для такой простой вещи. Проверьте ответ ccalboni.
RollerCosta
1
Я думаю, что это хороший ответ. вам не нужно знать каждую ключевую строку
Джозеф Ву
9

Вот способ обновления с помощью индекса, например, foo[x] = 9где xключ, а 9 - значение.

var views = new Dictionary<string, bool>();

foreach (var g in grantMasks)
{
    string m = g.ToString();
    for (int i = 0; i <= m.Length; i++)
    {
        views[views.ElementAt(i).Key] = m[i].Equals('1') ? true : false;
    }
}
Мэтью
источник
13
m [i] .Equals ('1') уже оценивается как bool, так что добавление? правда: ложь не нужна
Вессель ван дер Линден
Я не знаю, насколько эффективна эта логика, но мне нравится идея цикла For. :)
открыт и бесплатный
2
  1. обновить - изменить только существующие. Чтобы избежать побочного эффекта использования индексатора:

    int val;
    if (dic.TryGetValue(key, out val))
    {
        // key exist
        dic[key] = val;
    }
  2. обновить или (добавить новое, если значение не существует в dic)

    dic[key] = val;

    например:

    d["Two"] = 2; // adds to dictionary because "two" not already present
    d["Two"] = 22; // updates dictionary because "two" is now present
Влад Новаковский
источник
1

Это может работать для вас:

Сценарий 1: примитивные типы

string keyToMatchInDict = "x";
int newValToAdd = 1;
Dictionary<string,int> dictToUpdate = new Dictionary<string,int>{"x",1};

if(!dictToUpdate.ContainsKey(keyToMatchInDict))
   dictToUpdate.Add(keyToMatchInDict ,newValToAdd );
else
   dictToUpdate[keyToMatchInDict] = newValToAdd; //or you can do operations such as ...dictToUpdate[keyToMatchInDict] += newValToAdd;

Сценарий 2: подход, который я использовал для списка в качестве значения

int keyToMatch = 1;
AnyObject objInValueListToAdd = new AnyObject("something for the Ctor")
Dictionary<int,List<AnyObject> dictToUpdate = new Dictionary<int,List<AnyObject>(); //imagine this dict got initialized before with valid Keys and Values...

if(!dictToUpdate.ContainsKey(keyToMatch))
   dictToUpdate.Add(keyToMatch,new List<AnyObject>{objInValueListToAdd});
else
   dictToUpdate[keyToMatch] = objInValueListToAdd;

Надеюсь, что это полезно для тех, кто нуждается в помощи.

Мистер питт
источник