Wie aktualisiere ich std :: map nach der find-Methode?


87

Wie aktualisiere ich den Wert eines Schlüssels std::mapnach Verwendung der findMethode?

Ich habe eine Map- und Iterator-Deklaration wie folgt:

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

Ich verwende die Karte, um die Anzahl der Vorkommen eines Charakters zu speichern.

Ich verwende Visual C ++ 2010.

Antworten:


127

std::map::findGibt einen Iterator an das gefundene Element zurück (oder an das, end()wenn das Element nicht gefunden wurde). Solange das mapnicht const ist, können Sie das Element ändern, auf das der Iterator zeigt:

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
Vielen Dank. Ist es auch möglich, den Operator [] zu verwenden?
Jaykumarark

1
@ Jay: Ja, aber das Verhalten ist anders. In der mapDokumentation finden Sie die verschiedenen Funktionen von map.
James McNellis

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

1
@ jaykumarark Ich denke ja, aber der Nachteil dieser Lösung ist, dass die Karte den Ort des Elements zum zweiten Mal finden muss (das erste Mal ist Ihre Call-of-Find-Methode), was eine Operation mit log (N) -Komplexität ist. Es ist eine unnötige Verdoppelung derselben Operation.
Wahrheitssucher

50

Ich würde den Operator [] verwenden.

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'

Mit dieser Technik wird es wirklich einfach, alle Zeichen aus einem Stream zu lesen und zu zählen:

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
Ihre Antwort ist großartig für die eigentliche Frage - leider hat der Fragesteller es versäumt, dies auf offensichtliche Weise zu stellen (und daher zu akzeptieren). Aus diesem Grund denke ich, dass es noch besser wäre, eine kurze Aussage zu dieser Tatsache zu machen: Leute, die sehr schnell "lesen", könnten glauben, dass Sie vorschlagen, sie nach der Verwendung zu []verwenden find(ich glaube nicht, dass dies Ihre Absicht war).
Wolf

Nun, ich denke, 'finden' kann besser sein, wenn man ein Element nicht implizit einfügen möchte . Es kann vorzuziehen sein, das Finden und Sterben durch SIGSEGV abzuleiten.
Gwangmu Lee

1
@GwangmuLee Das De-Referenzieren des end()Iterators ist ein undefiniertes Verhalten, das nicht generiert werden muss SIGSEGV(und meiner Erfahrung nach ist dies unwahrscheinlich).
Martin York

4

Sie können std::map::atdie Elementfunktion verwenden. Sie gibt einen Verweis auf den zugeordneten Wert des mit dem Schlüssel k identifizierten Elements zurück.

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

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

1

Wenn Sie den Schlüssel bereits kennen, können Sie den Wert an diesem Schlüssel direkt mit aktualisieren m[key] = new_value

Hier ist ein Beispielcode, der helfen könnte:

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

Sie können auch so tun-

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

0

Sie können den Wert wie folgt aktualisieren

   auto itr = m.find('ch'); 
     if (itr != m.end()){
           (*itr).second = 98;
     }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.