¿Cómo actualizar std :: map después de usar el método de búsqueda?

90

¿Cómo actualizar el valor de una clave std::mapdespués de usar el findmétodo?

Tengo un mapa y una declaración de iterador como esta:

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

Estoy usando el mapa para almacenar el número de apariciones de un personaje.

Estoy usando Visual C ++ 2010.

Jaykumarark
fuente

Respuestas:

130

std::map::finddevuelve un iterador al elemento encontrado (o al end()si no se encontró el elemento). Siempre que mapno sea constante, puede modificar el elemento al que apunta el iterador:

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;
James McNellis
fuente
2
Gracias. ¿También es posible utilizar el operador []?
jaykumarark
1
@Jay: Sí, pero el comportamiento es diferente. Consulte la mapdocumentación para conocer las diversas funciones proporcionadas por map.
James McNellis
3
Tengo error: assignment of member 'std::pair<char* const, char*>::second' in read-only object:(
Tom Brito
1
@jaykumarark Creo que sí, pero la desventaja de esta solución es que el mapa debe encontrar la ubicación del elemento por segunda vez (la primera vez es la llamada al método de búsqueda), que es una operación con complejidad de registro (N). Es innecesaria la duplicación de una misma operación.
buscador de la verdad
51

Usaría el operador [].

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'

Entonces, al usar esta técnica, es realmente fácil leer todos los caracteres de una secuencia y contarlos:

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
}
Martin York
fuente
3
Su respuesta es excelente para la pregunta real ; lamentablemente, el autor de la pregunta no lo hizo (y por lo tanto lo aceptó) de una manera obvia. Por eso creo que sería incluso mejor hacer una breve declaración sobre este hecho: las personas que "leen" muy rápido, pueden creer que estás sugiriendo usar []después de haberlo usado find(no creo que esa sea tu intención).
Wolf
Bueno, creo que 'buscar' puede ser mejor si uno no quiere insertar implícitamente un elemento. Desreferir 'buscar' y morir por SIGSEGV puede ser preferible.
Gwangmu Lee
1
@GwangmuLee Desreferenciar el end()iterador es un comportamiento indefinido que no necesita generar un SIGSEGV(y en mi experiencia es poco probable que lo haga).
Martin York
5

Puede usar la std::map::atfunción miembro, devuelve una referencia al valor mapeado del elemento identificado con la clave k.

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

  mymap.at('a') = 10;
  mymap.at('b') = 20;
Manish Sogi
fuente
1

Si ya conoce la clave, puede actualizar directamente el valor en esa clave usando m[key] = new_value

Aquí hay un código de muestra que puede ayudar:

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    
abhinav1602
fuente
0

También puedes hacer esto-

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

Puede actualizar el valor como sigue

   auto itr = m.find('ch'); 
     if (itr != m.end()){
           (*itr).second = 98;
     }
ZAFIR AHMAD
fuente