Jak zaktualizować wartość przechowywaną w słowniku w C #?

455

Jak zaktualizować wartość określonego klucza w słowniku Dictionary<string, int>?

Amit
źródło
Mam złożony typ przechowywany jako wartość w słowniku. Kiedy chcę zmienić właściwość przechowywanej wartości, otrzymuję CS1612. Dlatego muszę się obejść: var v = dict [c]; v.dprop = c.sprop; dict [c] = v;
peter70

Odpowiedzi:

762

Wystarczy wskazać słownik na dany klucz i przypisać nową wartość:

myDictionary[myKey] = myNewValue;
ccalboni
źródło
Ta prosta metoda wydaje się więc lepiej zastępować dobrze znaną metodę „.Add” i „.TryGetValue” bez konieczności zmiany wartości. (?) Przynajmniej, jeśli nie ma znaczenia nadpisywanie kluczy, na przykład w sytuacji, gdy nie jest wykluczone, że klucze są zapisywane więcej niż raz w pętli. Czy ktoś widzi jakieś wady? Zwłaszcza, że ​​.Add ma ptifall dla początkujących, że jeśli zapomnisz o wrapperu lub TryGetValue, może on działać dobrze w testach, a przy innych danych testowych, w których .Add jest wywoływany dwukrotnie dla tego samego klucza, wygeneruje wyjątek.
Philm
1
ciekawym punktem tej operacji jest to, że UPSERT (klucz, wartość) do słownika. znakomity!
Soren
1
Jak stwierdził Pini, powinna to być odpowiedź na pytanie. z powodu właściwej rzeczy i zmień to.
Leo Gurdian,
190

Jest to możliwe, uzyskując dostęp do klucza jako indeksu

na przykład:

Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary["test"] = 1;
dictionary["test"] += 1;
Console.WriteLine (dictionary["test"]); // will print 2
Amit
źródło
11
Jeśli na liście nie ma pozycji „test”, wówczas lista [„test”] = lista [„test”] + 1; podniesie wyjątek KeyNotFoundException! Działa czyste przypisanie nieistniejącego indeksatora. list [„test”] = 1;
Steven Spyrka
Czy możesz również użyć list [„test”] ++ ;?
aufty
17
nie dzwoń do słownika, nazywaj go psami lub kotami lub
dyktuj
1
@aufty można napisać ++dictionary["test"];lub dictionary["test"]++;ale tylko wtedy, gdy istnieje wpis w słowniku z wartości klucza „test” - przykład: if(dictionary.ContainsKey("test")) ++dictionary["test"]; else dictionary["test"] = 1; // create entry with key "test"
gerryLowry
46

Możesz zastosować to podejście:

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

Zaletą jest to, że sprawdzasz i uzyskujesz wartość odpowiedniego klucza w zaledwie 1 dostępie do słownika. Jeśli użyjesz, ContainsKeyaby sprawdzić istnienie i zaktualizować wartość za pomocą dic[key] = val + newValue;, uzyskujesz dwukrotnie dostęp do słownika.

max_force
źródło
4
Zamiast dic.Add(key, newValue);ciebie możesz użyć dic[key] = newvalue;.
Macke,
Co się stanie, jeśli wykonasz „dic [klucz] = wartość” i „klucz” nie istnieje?
superpuccio,
1
@ superpuccio otrzymujesz KeyNotFoundException
ntroncos
8
@ntroncos nieprawda, doda ten klucz do słownika z podaną wartością. + = nie będzie działał na nieistniejącym kluczu, ponieważ jest to po prostu cukier składniowy dla dic [klucz] = wartość + dic [klucz].
lastas
2
To powinna być odpowiedź na pytanie dotyczące aktualizacji słownika, a nie tylko jego dodawania.
The Lonely Coder,
15

Użyj LINQ: Dostęp do słownika dla klucza i zmień wartość

Dictionary<string, int> dict = new Dictionary<string, int>();
dict = dict.ToDictionary(kvp => kvp.Key, kvp => kvp.Value + 1);
INT_24h
źródło
Nawet nie rozumiem, jak to działa, ale to niesamowite
heksagonest
1
Tworzenie kolejnego słownika nie ma dla mnie sensu dla tak prostej rzeczy. Sprawdź odpowiedź ccalboni.
RollerCosta
1
myślę, że to dobra odpowiedź. nie wymaga znajomości każdego klucza
Joseph Wu
9

Oto sposób aktualizacji według indeksu, podobnie jak foo[x] = 9gdzie xjest klucz, a 9 to wartość

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;
    }
}
Mateusz
źródło
13
m [i] .Equals ('1') już ocenia na bool, więc dodawanie? prawda: fałsz nie jest konieczny
Wessel van der Linden
Nie wiem, jak skuteczna jest ta logika, ale podoba mi się pomysł na pętlę For. :)
otwarte i darmowe
2
  1. aktualizacja - modyfikuj tylko istniejące. Aby uniknąć skutków ubocznych używania indeksatora:

    int val;
    if (dic.TryGetValue(key, out val))
    {
        // key exist
        dic[key] = val;
    }
  2. zaktualizuj lub (dodaj nowy, jeśli wartość nie istnieje w trybie dic)

    dic[key] = val;

    na przykład:

    d["Two"] = 2; // adds to dictionary because "two" not already present
    d["Two"] = 22; // updates dictionary because "two" is now present
Vlad Novakovsky
źródło
1

To może Ci pomóc:

Scenariusz 1: typy pierwotne

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;

Scenariusz 2: Podejście zastosowane w przypadku Listy jako wartości

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;

Mam nadzieję, że jest to przydatne dla kogoś, kto potrzebuje pomocy.

Pan Pitt
źródło