Як оновити std :: map після використання методу find?


90

Як оновити значення ключа в std::mapпісля використання findметоду?

У мене є декларація карти та ітератора, така:

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

Я використовую карту, щоб зберігати кількість повторень символу.

Я використовую Visual C ++ 2010.

Відповіді:


130

std::map::findповертає ітератор до знайденого елемента (або до end()елемента if, якщо елемент не знайдено). До тих пір, mapпоки не є const, ви можете змінити елемент, на який вказує ітератор:

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
Дякую. Чи можна також використовувати оператор []?
jaykumarark

1
@Jay: Так, але поведінка інша. Дивіться в mapдокументації для різних функцій , що надаються map.
James McNellis

3
Я отримав error: assignment of member 'std::pair<char* const, char*>::second' in read-only object:(
Том Бріто

1
@jaykumarark Я думаю, що так, але недоліком цього рішення є те, що карта повинна знаходити розташування елемента вдруге (перший раз - це ваш метод виклику пошуку), що є операцією зі складністю журналу (N). Потрібно дублювати ту саму операцію.
шукач правди

51

Я б використовував оператор [].

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'

Тож, використовуючи цю техніку, стає дуже легко прочитати всіх персонажів з потоку та підрахувати їх:

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
Ваша відповідь чудова для фактичного питання - на жаль, хто запитував, пропустив це (і, отже, прийняти) це очевидним чином. Ось чому я думаю, що було б ще краще коротко висловитись про цей факт: люди, які "читають" дуже швидко, можуть повірити, що ви пропонуєте використовувати []після використання find(я не думаю, що це був ваш намір).
Вовк

Ну, я думаю, "знайти" може бути краще, якщо ніхто не хоче неявно вставляти елемент. Відкласти "знахідку" та померти за допомогою SIGSEGV може бути кращим.
Gwangmu Lee

1
@GwangmuLee Зняття посилання на end()ітератор є невизначеною поведінкою, яку йому не потрібно генерувати SIGSEGV(і, на мій досвід, навряд чи це буде зроблено).
Martin York

5

Ви можете використовувати std::map::atфункцію-член, вона повертає посилання на відображене значення елемента, ідентифікованого за допомогою ключа k.

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

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

1

Якщо ви вже знаєте ключ, ви можете безпосередньо оновити значення за цим ключем за допомогою m[key] = new_value

Ось зразок коду, який може допомогти:

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

Ви також можете зробити так:

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

0

Ви можете оновити значення наступним чином

   auto itr = m.find('ch'); 
     if (itr != m.end()){
           (*itr).second = 98;
     }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.