Comment mettre à jour la valeur stockée dans Dictionary en C #?


455

Comment mettre à jour la valeur d'une clé spécifique dans un dictionnaire Dictionary<string, int>?


J'ai un type complexe stocké comme valeur dans le dictionnaire. Lorsque je souhaite modifier une propriété d'une valeur stockée, j'obtiens CS1612. Je dois donc contourner: var v = dict [c]; v.dprop = c.sprop; dict [c] = v;
peter70

Réponses:


762

Pointez simplement le dictionnaire sur la clé donnée et attribuez une nouvelle valeur:

myDictionary[myKey] = myNewValue;

Cette méthode simple semble donc également être un meilleur substitut aux méthodes bien connues ".Add" et ".TryGetValue" sans qu'il soit nécessaire de modifier la valeur. (?) Au moins, si cela n'a pas d'importance d'écraser des clés, par exemple dans une situation où il n'est pas exclu que les clés soient écrites plus d'une fois dans une boucle. Ou quelqu'un voit-il des inconvénients? Surtout parce que .Add a le ptifall pour les débutants que si le if-wrapper ou TryGetValue est oublié, il peut fonctionner correctement dans les tests et avec d'autres données de test où .Add est appelé deux fois pour la même clé, il lèvera une exception.
Philm

1
le point intéressant de cette opération est que, il UPSERT (clé, valeur) dans le dictionnaire. brillant!
Soren

1
Comme l'a déclaré Pini, cela devrait être la réponse à la question. en raison de la bonne chose et le changer.
Leo Gurdian

190

C'est possible en accédant à la clé comme index

par exemple:

Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary["test"] = 1;
dictionary["test"] += 1;
Console.WriteLine (dictionary["test"]); // will print 2

11
S'il n'y a pas d'élément "test" dans la liste, alors list ["test"] = list ["test"] + 1; va lever KeyNotFoundException! L'affectation pure d'un indexeur non existant fonctionnera. list ["test"] = 1;
Steven Spyrka

Pouvez-vous également utiliser list ["test"] ++ ;?
2016

17
ne pas appeler une liste de dictionnaires, appeler chiens ou chats ou dict
user3800527

1
@aufty vous pouvez écrire ++dictionary["test"];ou dictionary["test"]++;mais seulement s'il y a une entrée dans le dictionnaire avec la valeur clé "test" - exemple: if(dictionary.ContainsKey("test")) ++dictionary["test"]; else dictionary["test"] = 1; // create entry with key "test"
gerryLowry

46

Vous pouvez suivre cette approche:

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

L'avantage que vous obtenez ici est que vous vérifiez et obtenez la valeur de la clé correspondante en seulement 1 accès au dictionnaire. Si vous utilisez ContainsKeypour vérifier l'existence et mettre à jour la valeur à l'aide de, dic[key] = val + newValue;vous accédez au dictionnaire deux fois.


4
Au lieu de dic.Add(key, newValue);vous pouvez utiliser use dic[key] = newvalue;.
Macke

Que se passe-t-il si vous faites "dic [key] = value" et "key" n'existe pas?
superpuccio

1
@superpuccio vous obtenez une exception KeyNotFoundException
ntroncos

8
@ntroncos pas vrai, il ajoutera cette clé au dictionnaire avec la valeur fournie. + = ne fonctionnera pas sur une clé non existante, car il s'agit simplement de sucre syntaxique pour dic [clé] = valeur + dic [clé].
lastas

2
Cela devrait être la réponse à la question en ce qui concerne la mise à jour du dictionnaire et non seulement son ajout.
The Lonely Coder

15

Utilisez LINQ: accès au dictionnaire pour la clé et modifiez la valeur

Dictionary<string, int> dict = new Dictionary<string, int>();
dict = dict.ToDictionary(kvp => kvp.Key, kvp => kvp.Value + 1);

Je ne comprends même pas comment cela fonctionne, mais c'est incroyable
hexagone

1
Créer un autre dictionnaire n'a pas de sens pour moi pour une chose aussi simple. Vérifiez la réponse de ccalboni.
RollerCosta

1
je pense que c'est une bonne réponse. cela ne vous oblige pas à connaître chaque chaîne de clé
Joseph Wu

9

Voici un moyen de mettre à jour par un index un peu comme foo[x] = 9xest une clé et 9 est la valeur

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
le m [i] .Equals ('1') évalue déjà à un booléen, donc en ajoutant? vrai: faux n'est pas nécessaire
Wessel van der Linden

Je ne sais pas à quel point cette logique est efficace, mais j'aime l'idée de boucle For. :)
ouvert et gratuit

2
  1. mise à jour - modifie l'existant uniquement. Pour éviter les effets secondaires de l'utilisation de l'indexeur:

    int val;
    if (dic.TryGetValue(key, out val))
    {
        // key exist
        dic[key] = val;
    }
  2. mettre à jour ou (ajouter un nouveau si la valeur n'existe pas dans le dic)

    dic[key] = val;

    par exemple:

    d["Two"] = 2; // adds to dictionary because "two" not already present
    d["Two"] = 22; // updates dictionary because "two" is now present

1

Cela peut fonctionner pour vous:

Scénario 1: types primitifs

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;

Scénario 2: l'approche que j'ai utilisée pour une liste en tant que valeur

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;

J'espère que c'est utile pour quelqu'un qui a besoin d'aide.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.