为啥简单的算术减法在“if”条件下不起作用?
Posted
技术标签:
【中文标题】为啥简单的算术减法在“if”条件下不起作用?【英文标题】:Why does the simple arithmetic subtraction not work in the "if" condition?为什么简单的算术减法在“if”条件下不起作用? 【发布时间】:2020-07-08 11:57:18 【问题描述】:我有 2 个数组,其中包含元素。我使用散列来获取每个元素出现多次的频率。 mapcheckA
包含第一个数组元素的频率,mapcheckB
包含另一个数组的频率。我正在尝试从两个无序地图中删除/擦除任何重复的元素。这是执行此操作的代码:
for (auto i : mapcheckA)
if (mapcheckB.find(i.first) != mapcheckB.end())
if (i.second >=
mapcheckB.find(i.first)
->second) // This block of code doesn't work as expected
i.second -= mapcheckB.find(i.first)->second;
mapcheckB.erase(i.first);
else
mapcheckB.find(i.first)->second -= i.second;
mapcheckA.erase(i.first);
for (auto i1 : mapcheckA)
cout << i1.first << "\t" << i1.second << endl;
for (auto i : mapcheckB)
cout << i.first << "\t" << i.second << endl;
当我以这样的方式输入元素时,第一个数组包含的元素频率比第二个数组中的频率高,如下所示:
arrayA = [ 1, 1, 1, 1, 4, 4 ]; // Here frequency of "1" is 4.
arrayB = [ 2, 2, 1, 1, 3, 3 ]; // Here frequency of "1" is 2.
在这种情况下,“if”条件下的代码块不会将频率从 1 更改为 2。 如果我更改数组的顺序,则代码可以正常工作。我在这里做错了什么?
【问题讨论】:
当我打印键值对时,对于上述 2 个数组,输出为: 对于 arrayA:4 2
1 4
对于 arrayB:3 2
2 2
在循环 for (auto i : mapcheckA)
中,您正在对元素的副本进行操作,您的意思是要对实际对象 (for (auto& i : mapcheckA)
) 的引用进行操作吗?
@AlgirdasPreidžius 在i
之前在for (auto i: mapcheckA)
中插入&
后,问题就解决了。但我不明白为什么以及如何解决它。
@BennyK 但它工作正常。当第二个数组中某个元素的频率大于第一个时,输出是正确的。当第一个数组中的频率大于第二个时,我遇到了问题。
@Thomas Sablik - 抱歉,错过了“无序地图”部分。
【参考方案1】:
您有两个重大错误:
处理数据的副本(已在 cmets 中标识)。使用引用意味着更改将反映在原始容器中,而不是在副本超出范围时被丢弃。
for (auto& i : mapcheckA) // 添加 &
未定义的行为 在您的“其他”情况下,您删除迭代中的当前元素,使迭代器 i 无效,但循环继续增加 i。程序状态不确定,不能这样做。
不幸的是,对于范围广泛的 for 循环,没有好的方法可以做到这一点。您的选择:
记住键(或迭代器)以备后用,并在循环后删除它们
手动滚动循环以进行手动迭代器递增:
for (auto i = begin(mappedA), e = end(mappedA); i != e; )
if (...)
...
++i;
else
...
i = mappedA.erase(i);
此外,您可以考虑使用 c++ 结构化绑定 以使代码更具可读性并减少相同的查找次数。综上所述:
for (auto iterA = begin(mapcheckA), endA = end(mapcheckA); iterA != endA; )
auto& [keyA, valueA] = *iterA;
if (auto iterB = mapcheckB.find(keyA); iterB != end(mapcheckB))
auto& [keyB, valueB] = *iterB;
if (valueA >= valueB)
valueA -= valueB;
mapcheckB.erase(iterB);
++iterA;
else
valueB -= valueA;
iterA = mapcheckA.erase(iterA);
注意:if 的两半都会更新 iterA,而不是在 for 循环中进行,因为其中一个使用 ++,而另一个获取调用擦除的结果。
【讨论】:
以上是关于为啥简单的算术减法在“if”条件下不起作用?的主要内容,如果未能解决你的问题,请参考以下文章
Alter Table 在 MS Access 64 位下不起作用。为啥?
为啥 webview_flutter 在添加到应用程序(iOS)的情况下不起作用?