Як оновити значення, що зберігається у словнику в C #?


455

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


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

Відповіді:


762

Просто вкажіть на словник на заданій клавіші та призначте нове значення:

myDictionary[myKey] = myNewValue;

Тож цей простий метод здається також кращою заміною добре відомим методам ".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

11
Якщо в списку немає елемента "тест", тоді список ["тест"] = список ["тест"] + 1; підніме KeyNotFoundException! Чисте призначення неіснуючого індексатора спрацює. список ["тест"] = 1;
Стівен Шпирка

Чи можете ви також використовувати список ["тест"] ++ ;?
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;ви отримуєте доступ до словника двічі.


4
Замість dic.Add(key, newValue);вас можна використовувати використання dic[key] = newvalue;.
Макке

Що станеться, якщо у вас "dic [ключ] = значення" та "ключ" не існує?
superpuccio

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

Я навіть не розумію, як це працює, але це дивно
шестикутник

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') вже оцінює булінг, тому додаючи? правда: неправда не потрібна
Вессель ван дер Лінден

Я не знаю, наскільки ефективна ця логіка, але мені подобається ідея для циклу. :)
відкрито та безкоштовно

2
  1. update - змінювати лише існуючі. Щоб уникнути побічного ефекту використання індексатора:

    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;

Сподіваюся, це корисно для того, хто потребує допомоги.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.