Редактирование значения в неупорядоченной карте для данного ключа

Ниже приведен код C++ для подсчета слов в журнале. Я пытаюсь добавить слово, если его значение не существует, а если существует, увеличить его.

unordered_map<string,int>hash;
vector<string> magazine(m);

for(int i = 0;i <m;i++)
{
   cin >> magazine[i];
   if(hash[magazine[i]]>0)
       hash[magazine[i]]++;
   else
    hash.emplace(magazine[i],1);
}

Но когда я пытаюсь вывести, все ключи журнала дают значение 0. Есть идеи, почему?


person Bharg    schedule 24.10.2016    source источник
comment
if(hash[magazine[i]]>0) что ты делаешь?   -  person juanchopanza    schedule 24.10.2016
comment
Прочитайте Как отлаживать небольшие программы Эрика Липперта. . Ваш отладчик — правильный инструмент для ответа на этот вопрос.   -  person Martin Bonner supports Monica    schedule 24.10.2016


Ответы (3)


Ваша версия не работает, потому что этот if(hash[magazine[i]]>0) вставит элемент в hash, если он не существует, этот новый элемент будет иметь отображаемое значение 0¹. Это означает, что hash.emplace(magazine[i],1); здесь бессмысленно, потому что теперь всегда будет элемент в magazine[i]. Поскольку его значение будет 0, ваш hash[magazine[i]]++; тоже никогда не запустится, потому что if никогда не будет true. У вас остается карта из i элементов со значением 0.

operator[] возвращает ссылку на сопоставленное значение, если оно есть, если нет, он вставляет один, а затем возвращает эту ссылку¹.

Это означает, что вы можете выделить if и просто изменить его на:

for(int i = 0;i <m;i++)
{
   cin >> magazine[i];
   ++hash[magazine[i]];
}

Что в основном означает: "Получите ссылку на сопоставленное значение для ключа magazine[i], если ничего не найдено, вставьте и дайте мне его. Увеличьте эту ссылку"."

¹: Если происходит вставка, элемент инициализируется значением. Поскольку тип отображаемого значения — int, это приведет к тому, что после вставки сопоставленное значение будет 0.

person Hatted Rooster    schedule 24.10.2016
comment
Пожалуйста, добавьте к ответу, что вновь созданное значение инициализировано по умолчанию, что означает, что оно содержит значение 0 для числовых типов. - person Leon; 24.10.2016
comment
Это работает, но вы не объяснили, почему предыдущая версия не работала (это то, о чем на самом деле спрашивал ОП). - person Martin Bonner supports Monica; 24.10.2016
comment
@Leon Он инициализирован value, что означает, что он содержит значение 0 для числовых типов. Инициализация числовых типов по умолчанию ничего не делает. - person user703016; 24.10.2016

if(hash[magazine[i]]>0) создает новый элемент, если ключ не существует.

То, что вы действительно хотите, это:

if(hash.find(magazine[i])!=hash.end())

Как упоминал @juanchopanza, вам не нужно ветвление. std::unordered_map::operator [] может справиться с этим следующим образом:

hash[magazine[i]]++;
person Humam Helfawi    schedule 24.10.2016
comment
Нет, им не нужны никакие условия. Только 1_. - person juanchopanza; 24.10.2016
comment
Или полностью удалите if и просто используйте hash[magazine[i]]++;. Элемент будет создан со значением 0, если это необходимо, а затем будет увеличен. Это является вариантом использования для индексации карты, создающей элемент, если он не существует, но я все же считаю, что это было неправильное решение. - person Martin Bonner supports Monica; 24.10.2016
comment
@juanchopanza Вы имеете в виду, что по умолчанию он равен 0, а ++ отвечает за то, чтобы сделать его равным 1? даже в этом случае ОП нуждается в разъяснении того, что происходит и какова точная альтернатива ИМО. - person Humam Helfawi; 24.10.2016
comment
Не совсем, hash[magazine[i]]++; здесь всегда ответ. - person Hatted Rooster; 24.10.2016
comment
@HumamHelfawi Да, хорошо указать, что не так. Я попытался заставить их понять это, задав вопрос в комментариях. - person juanchopanza; 24.10.2016
comment
Я думаю, вам нужно указать, что .emplace ничего не сделает, если элемент уже существует (и тест гарантирует, что это так) - таким образом, элемент останется нулевым, и в следующий раз в цикле произойдет то же самое. - person Martin Bonner supports Monica; 24.10.2016
comment
@juanchopanza @Martin @GillBates hash[magazine[i]]++; не отвечает на вопрос, заданный OP. Это (возможно) полезный комментарий для добавления к ответу. - person Galik; 24.10.2016
comment
@Galik: Согласен. Отсюда мой комментарий о том, что emplace ничего не делает, потому что элемент существует. - person Martin Bonner supports Monica; 24.10.2016

Вы непреднамеренно создаете новый элемент на карте, выполняя:

if(hash[magazine[i]]>0)

map<>::operator[] выполняет вставку, инициализацию значения (это значение равно нулю в вашем случае), а затем возвращает ссылку на значение, все очень осторожно.

Как правильно указано во многих комментариях, лучший способ:

hash[key]++ 

Подробнее.

person Saurav Sahu    schedule 24.10.2016