Comment mettre à jour std :: map après avoir utilisé la méthode find?


90

Comment mettre à jour la valeur d'une clé std::mapaprès avoir utilisé la findméthode?

J'ai une carte et une déclaration d'itérateur comme celle-ci:

map <char, int> m1;
map <char, int>::iterator m1_it;
typedef pair <char, int> count_pair;

J'utilise la carte pour stocker le nombre d'occurrences d'un personnage.

J'utilise Visual C ++ 2010.

Réponses:


130

std::map::findrenvoie un itérateur vers l'élément trouvé (ou vers le end()si l'élément n'a pas été trouvé). Tant que le mapn'est pas const, vous pouvez modifier l'élément pointé par l'itérateur:

std::map<char, int> m;
m.insert(std::make_pair('c', 0));  // c is for cookie

std::map<char, int>::iterator it = m.find('c'); 
if (it != m.end())
    it->second = 42;

2
Merci. Est-il également possible d'utiliser l'opérateur []?
jaykumarark

1
@Jay: Oui, mais le comportement est différent. Consultez la mapdocumentation pour les différentes fonctions fournies par map.
James McNellis

3
J'ai eu error: assignment of member 'std::pair<char* const, char*>::second' in read-only object:(
Tom Brito

1
@jaykumarark Je pense que oui, mais l'inconvénient de cette solution est que la carte doit trouver l'emplacement de l'élément une deuxième fois (la première fois est votre appel à la méthode de recherche) qui fonctionne avec une complexité log (N). C'est une duplication inutile de la même opération.
véritéseeker

51

J'utiliserais l'opérateur [].

map <char, int> m1;

m1['G'] ++;  // If the element 'G' does not exist then it is created and 
             // initialized to zero. A reference to the internal value
             // is returned. so that the ++ operator can be applied.

// If 'G' did not exist it now exist and is 1.
// If 'G' had a value of 'n' it now has a value of 'n+1'

Donc, en utilisant cette technique, il devient vraiment facile de lire tous les caractères d'un flux et de les compter:

map <char, int>                m1;
std::ifstream                  file("Plop");
std::istreambuf_iterator<char> end;

for(std::istreambuf_iterator<char> loop(file); loop != end; ++loop)
{
    ++m1[*loop]; // prefer prefix increment out of habbit
}

3
Votre réponse est excellente pour la question réelle - malheureusement, le demandeur a manqué de poser (et donc d'accepter) cela de manière évidente. C'est pourquoi je pense qu'il serait encore mieux d'avoir une brève déclaration sur ce fait: les gens qui "lisent" très vite, pourraient croire que vous proposez d'utiliser []après avoir utilisé find(je ne pense pas que c'était votre intention).
Wolf

Eh bien, je pense que «trouver» peut être mieux si l'on ne veut pas insérer implicitement un élément. Déréférencer «trouver» et mourir par SIGSEGV peut être préférable.
Gwangmu Lee

1
@GwangmuLee Le déréférencement de l' end()itérateur est un comportement indéfini dont il n'a pas besoin pour générer un SIGSEGV(et d'après mon expérience, il est peu probable qu'il le fasse).
Martin York

5

Vous pouvez utiliser la std::map::atfonction membre, elle renvoie une référence à la valeur mappée de l'élément identifié avec la clé k.

std::map<char,int> mymap = {
                               { 'a', 0 },
                               { 'b', 0 },
                           };

  mymap.at('a') = 10;
  mymap.at('b') = 20;

1

Si vous connaissez déjà la clé, vous pouvez directement mettre à jour la valeur de cette clé en utilisant m[key] = new_value

Voici un exemple de code qui pourrait vous aider:

map<int, int> m;

for(int i=0; i<5; i++)
    m[i] = i;

for(auto it=m.begin(); it!=m.end(); it++)
    cout<<it->second<<" ";
//Output: 0 1 2 3 4

m[4] = 7;  //updating value at key 4 here

cout<<"\n"; //Change line

for(auto it=m.begin(); it!=m.end(); it++)
    cout<<it->second<<" ";
// Output: 0 1 2 3 7    

0

Vous pouvez aussi faire comme ça-

 std::map<char, int>::iterator it = m.find('c'); 
 if (it != m.end())
 (*it).second = 42;

0

Vous pouvez mettre à jour la valeur comme suit

   auto itr = m.find('ch'); 
     if (itr != m.end()){
           (*itr).second = 98;
     }
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.