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.