【问题标题】:Increment an iterator standard map增加一个迭代器标准映射
【发布时间】:2015-05-03 09:50:48
【问题描述】:

所有,

std::map<int, std::string> addressee;
std::map<int, std::string>::iterator it1, it2;

for( it1 = addressee.begin(); it1 != addressee().end(); it1++ )
{
    bool found = false;
    for( it2 = it1 + 1; it2 != addressee.end() && !found; it2++ )
    {
       if( it1->second == it1->second )
       {
           printf( "Multiple occurences of addressees found" );
           found = true;
       }
    }
}

gcc 报错:no match for operator+。

此代码是我现在尝试做的简化版本。我想我可以使用 std::advance(),但它似乎只是在浪费函数调用。

有没有更好的解决方法?

【问题讨论】:

  • “浪费了一个函数调用”。函数调用不是“浪费”。
  • it2 = it1; ++it2; 在循环之前然后for(; it2 != ...)
  • @MooingDuck,不,这不是浪费。但它需要一些我宁愿避免的额外操作。这需要一些时间来完成。
  • @Rado,最简单的解决方案。谢谢你。我想我必须从不同的角度来看待它。
  • @Igor:你在想什么“额外的操作”?你认为它“需要”多少“时间”?你量过吗?如果你这样做了,你会感到惊讶。现在你只是在猜测,从这些猜测中得出错误的结论,然后使用这些错误的结论得出错误的解决方案(或者更确切地说,跳过正确的解决方案)。

标签: c++ dictionary iterator


【解决方案1】:

std::map 没有随机访问迭代器,只有双向迭代器,所以没有+ n 操作。相反,请使用std::next:

#include <iterator>
#include <map>

// ...

for (auto it1 = addressee.begin(), e = addressee.end(); it1 != e; ++it1)
{
    for (auto it2 = std::next(it1); it2 != e; ++it2)
    {
        if (it1->second == it2->second)
        {
            // ...
            break;
        }
    }
}

事实上,您应该始终使用std::next,因为它知道它的参数具有哪个迭代器类别以及计算下一个迭代器的最有效方法是什么。这样,您就不必关心您碰巧使用的特定容器。

【讨论】:

    【解决方案2】:

    @Kerrek 已经指出了如何处理您在句法级别遇到的问题。

    我将在算法层面考虑这个问题——你真正想要从整体上完成什么,而不是仅仅着眼于如何修复特定的代码行。

    除非所涉及的集合非常可靠很小所以这个操作的效率根本不重要,我会从集合中复制映射值,然后使用sort 和unique 看看有没有重复的:

    std::vector<std::string> temp;
    
    std::transform(addressee.begin(), addressee.end(), 
                   std::back_inserter(temp),
                   [](std::pair<int, std::string> const &in) { return in.second; });
    
    std::sort(temp.begin(), temp.end());
    
    if (std::unique(temp.begin(), temp.end()) != temp.end()) {
       std::cout << "Multiple occurrences of addressees found";
       found = true;
    }
    

    这将复杂性从 O(N2) 降低到 O(N log N),如果集合非常大,这通常会相当可观。

    【讨论】:

    • 我自己会将所有内容放入 set 或 unordered_set 中,插入尚未在集合中的内容并报告已经存在的内容的重复项。
    • @Hurkyl:如果您期望看到很多重复项,这也是一个合理的可能性(但如果您要插入大多数项目,向量通常更快比 unordered_set,而且比 set 快很多。
    猜你喜欢
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 2013-01-27
    • 1970-01-01
    • 2021-04-15
    • 2011-07-31
    • 1970-01-01
    • 2018-04-04
    相关资源
    最近更新 更多