Jak zaktualizować std :: map po użyciu metody find?


90

Jak zaktualizować wartość klucza std::mappo użyciu findmetody?

Mam mapę i deklarację iteratora taką jak ta:

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

Używam mapy do przechowywania liczby wystąpień znaku.

Używam Visual C ++ 2010.

Odpowiedzi:


130

std::map::findzwraca iterator do znalezionego elementu (lub do elementu, end()jeśli element nie został znaleziony). Dopóki mapnie jest stała, możesz zmodyfikować element wskazywany przez iterator:

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
Dzięki. Czy można również użyć operatora []?
jaykumarark

1
@Jay: Tak, ale zachowanie jest inne. Zapoznaj się z mapdokumentacją dotyczącą różnych funkcji udostępnianych przez map.
James McNellis

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

1
@jaykumarark Myślę, że tak, ale wadą tego rozwiązania jest to, że mapa musi znaleźć lokalizację elementu po raz drugi (za pierwszym razem jest to wywołanie metody find), która jest operacją ze złożonością log (N). Jest to zbędne powielanie tej samej operacji.
poszukiwacz prawdy

51

Użyłbym operatora [].

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'

Dzięki tej technice odczytanie wszystkich znaków ze strumienia i policzenie ich staje się naprawdę łatwe:

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
Twoja odpowiedź jest świetna na rzeczywiste pytanie - niestety pytający nie mógł zadać (i dlatego zaakceptował) tego w oczywisty sposób. Dlatego myślę, że nawet lepiej byłoby mieć krótkie oświadczenie na ten temat: ludzie, którzy „czytają” bardzo szybko, mogą uwierzyć, że sugerujesz użycie []po użyciu find(nie sądzę, że był to twój zamiar).
Wilk

Cóż, myślę, że „znajdź” może być lepsze, jeśli nie chce się pośrednio wstawiać elementu. Preferowane może być wyeliminowanie „znalezienia” i umierania przez SIGSEGV.
Gwangmu Lee,

1
@GwangmuLee Odwołanie do end()iteratora jest niezdefiniowanym zachowaniem i nie musi generować plikuSIGSEGV (az mojego doświadczenia wynika, że ​​jest mało prawdopodobne).
Martin York,

5

Możesz użyć std::map::atfunkcji członkowskiej, zwraca ona referencję do zamapowanej wartości elementu identyfikowanego kluczem k.

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

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

1

Jeśli znasz już klucz, możesz bezpośrednio zaktualizować wartość w tym kluczu za pomocą m[key] = new_value

Oto przykładowy kod, który może pomóc:

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

Możesz też zrobić w ten sposób-

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

0

Możesz zaktualizować wartość, jak poniżej

   auto itr = m.find('ch'); 
     if (itr != m.end()){
           (*itr).second = 98;
     }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.