为给定的键编辑无序映射中的值

3
以下是获取杂志中单词计数的C++代码。如果单词不存在,则将其添加并增加其值;如果存在,则将其值加1。
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作为值。有什么想法吗?

2
如果(hash[magazine[i]]>0),你认为这是做什么的? - juanchopanza
阅读Eric Lippert的《如何调试小程序》。你的调试器是回答这个问题的正确工具。 - Martin Bonner supports Monica
3个回答

8
您的版本无法工作,因为此处的 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。

1
请在答案中添加一句话,说明新创建的值是默认初始化的,这意味着对于数字类型,它保持为0。 - Leon
这个可以运行,但你没有解释为什么之前的版本不行(这才是原帖提出的问题)。 - Martin Bonner supports Monica
1
@Leon 它是value初始化的,这意味着对于数字类型,它保持值为0。 数字类型的默认初始化不会做任何事情。 - user703016

1
你无意中通过以下方式在地图中创建了一个新元素:
if(hash[magazine[i]]>0)
map<>::operator[]进行插入、值初始化(在您的情况下该值为零),然后返回该值的引用,一切都非常谨慎地进行。
正如许多评论中正确建议的那样,最好的方法是:
hash[key]++ 

阅读更多。


1

if(hash[magazine[i]]>0) 如果键不存在,就会创建新的项目。

你真正想要的是:

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

正如@juanchopanza所提到的,你不需要分支。 std :: unordered_map :: operator [] 可以像这样处理它:
hash[magazine[i]]++;

1
不需要任何条件语句。只需要hash[magazine[i]]++;即可。 - juanchopanza
1
或者完全删除 if,只使用 hash[magazine[i]]++;。如果需要,该元素将被创建并赋值为0,然后递增。这确实是索引到映射中创建元素(如果不存在)的用例 - 尽管我仍然认为这是错误的决定。 - Martin Bonner supports Monica
1
@juanchopanza的意思是它默认为0,++负责使其变为1?即使如此,OP仍需要澄清正在发生的事情以及确切的替代方案。在我看来。 - Humam Helfawi
1
不是的,hash[magazine[i]]++; 总是正确的答案。 - Hatted Rooster
1
@juanchopanza @Martin @GillBates hash[magazine[i]]++;并没有回答OP所问的问题。这可能是一个有用的评论,可以添加到答案中。 - Galik
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接