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.