Come aggiornare std :: map dopo aver utilizzato il metodo find?


90

Come aggiornare il valore di una chiave in std::map dopo aver utilizzato il findmetodo?

Ho una dichiarazione di mappa e iteratore come questa:

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

Sto usando la mappa per memorizzare il numero di occorrenze di un personaggio.

Sto usando Visual C ++ 2010.

Risposte:


130

std::map::findrestituisce un iteratore all'elemento trovato (o end()se l'elemento non è stato trovato). Finché mapnon è const, puoi modificare l'elemento puntato dall'iteratore:

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
Grazie. È anche possibile utilizzare l'operatore []?
jaykumarark

1
@ Jay: Sì, ma il comportamento è diverso. Vedere la mapdocumentazione per le varie funzioni fornite da map.
James McNellis

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

1
@jaykumarark Penso di sì, ma lo svantaggio di questa soluzione è che la mappa deve trovare la posizione dell'elemento la seconda volta (la prima volta è la tua chiamata al metodo find) che è un'operazione con complessità log (N). Non è necessaria la duplicazione della stessa operazione.
truthseeker

51

Userei l'operatore [].

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'

Quindi usando questa tecnica diventa davvero facile leggere tutti i caratteri da uno stream e contarli:

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
La tua risposta è ottima per la domanda reale - purtroppo il richiedente ha mancato di chiederlo (e quindi di accettare) in modo ovvio. Ecco perché penso che sarebbe ancora meglio avere una breve dichiarazione su questo fatto: le persone che "leggono" molto velocemente, potrebbero credere che tu stia suggerendo di usare []dopo aver usato find(non credo che questa fosse la tua intenzione).
Wolf

Ebbene, penso che "trova" possa essere migliore se non si vuole inserire implicitamente un elemento. Può essere preferibile dissuadere il "ritrovamento" e morire da SIGSEGV.
Gwangmu Lee

1
@GwangmuLee De-referencing l' end()iteratore è un comportamento indefinito, non ha bisogno di generare un SIGSEGV(e nella mia esperienza è improbabile che lo faccia).
Martin York

5

È possibile utilizzare la std::map::atfunzione membro, restituisce un riferimento al valore mappato dell'elemento identificato con la chiave k.

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

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

1

Se conosci già la chiave, puoi aggiornare direttamente il valore in quella chiave utilizzando m[key] = new_value

Ecco un codice di esempio che potrebbe aiutare:

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

Puoi anche fare così-

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

0

Puoi aggiornare il valore come segue

   auto itr = m.find('ch'); 
     if (itr != m.end()){
           (*itr).second = 98;
     }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.