【问题标题】:c++ : double iteration through mapc ++:通过map进行双重迭代
【发布时间】:2015-06-17 15:51:41
【问题描述】:

我想遍历地图,但内部循环只会遍历元素的上部。 使用矢量它看起来像这样:

for(auto element1 = myVector.begin() ; element1 != myVector.end() ; ++element1){
    for(auto element2 = element1 + 1; element2 != myVector.end() ; ++element2){
         //my stuff
    }
}

但是使用地图element1 + 1 返回错误no operator matches this operand.. 我相信这是因为元素没有在地图中排序。

那么我该如何正确地做到这一点呢?我目前正在使用这种混乱的解决方法,需要在每个循环中进行测试:

for(auto element1 = myMap.begin() ; element1 != myMap.end() ; ++element1){
    for(auto element2 = element1; element2 != myMap.end() ; ++element2){
         if(element->first != element2->first)
         //my stuff
    }
}

【问题讨论】:

  • @Pixelchemist:对,我看不懂
  • map 中的元素按键排序。不能使用element1 + 1 的原因是与映射关联的迭代器不是随机访问迭代器。你可以增加它们,但你不能给它们加 1。

标签: c++ dictionary iterator


【解决方案1】:

您可以使用std::next 来执行此操作:

for(auto element1 = myMap.begin() ; element1 != myMap.end() ; ++element1) {
    for(auto element2 = std::next(element1) ; element2 != myMap.end() ; ++element2) {
        //my stuff
    }
}

这里是关于std::next 的一些附加背景信息。 std::next 有一个可选的第二个参数,它是传递的迭代器后面的元素数。例如std::next(element1, 2) 将返回element1 之后的第二个元素的迭代器。正如 cmets 中所指出的,您必须在使用 std::next 时要小心,尤其是在循环中。如果it 指向myMap.end() 之前的元素,那么使用std::next(it, 2) 会导致未定义的行为。您要确保使用它永远不会超过容器的末尾。

你可以把std::next想成是这样实现的:

// If distance is negative, then i must meet the requirements of BidirectionalIterator
// Otherwise, i must meet the requirements of ForwardIterator.
template<class ForwardIterator>
ForwardIterator next(ForwardInterator i, int distance) {
    for( ; distance < 0 ; ++distance) {
        --i;
    }
    for( ; distance > 0 ; --distance) {
        ++i;
    }

    return i;
}

可以这样等效地实现:

template<class ForwardIterator>
ForwardIterator next(ForwardIterator i, int distance) {
    std::advance(i, distance);
    return i;
}

【讨论】:

  • std::next(element1, 2) 不能在这里使用
  • @Slava 为什么? next() 采用前向迭代器,而映射具有双向迭代器。
  • @Daniel 因为 element2 在第一个循环结束时会越界
  • @Daniel:编译器会让你使用它,但你不能在这种特殊情况下使用它,因为当 element1 碰巧引用地图中的最后一个元素时,你会得到 undefined行为。
  • @MichaelBurr element1 永远不会等于 end 因为循环是 element1 != myMap.end()
【解决方案2】:

即使您不了解一些较新的 C++ 工具,例如 std::next()(这是解决此问题的好方法),这似乎是一个需要解决的相当基本的问题:

for(auto element1 = myMap.begin() ; element1 != myMap.end() ; ++element1){
    auto element2 = element1;
    ++element2;
    for(; element2 != myMap.end() ; ++element2){
         //my stuff
    }
}

【讨论】:

    【解决方案3】:

    最简单的解决方案是跳过第一个:

    for(auto element1 = myMap.begin() ; element1 != myMap.end() ; ++element1){
        for(auto element2 = element1; element2 != myMap.end() ; ++element2){
             if( element2 == element1 ) continue;
             //my stuff
        }
    }
    

    【讨论】:

    • 第二个 sn-p 也移动了element1,这不是故意的。
    • @timrau 它将 element1 移动到那里,而不是在第一个 for
    • 但是两个迭代器都跳过了第一个元素
    • @timrau 啊,你的意思是第一个迭代器很可能也会被使用,你是对的。已删除,谢谢。我不喜欢那个代码,我觉得它不正确。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    • 2020-10-18
    相关资源
    最近更新 更多