【问题标题】:C++ deque iterate to second last elementC++ deque 迭代到倒数第二个元素
【发布时间】:2017-04-07 06:39:01
【问题描述】:

我正在尝试遍历一个双端队列以排除最后一个条目。理想情况下,我会避免计算和比较长度,所以我尝试了

    auto it_end = dq.rbegin(); it_end++;
    for ( auto it = dq.begin(); it !=it_end; ) {
        if ( cond() ) {
            it = dq.erase( it );
        } else {
            it++;
        }
    }

但是编译器抱怨没有匹配操作数,这似乎可以理解,因为我有一个反向迭代器和一个常规迭代器。有没有一种优雅的方法可以在避免计数的最后一个元素之前停止?比如,偏移量? 我也尝试过使用 ussign,但结果证明是引用而不是迭代器,所以 != 也不满意。

【问题讨论】:

    标签: c++


    【解决方案1】:

    您可以在结束前使用dq.end() - 1 获得一个。

    您也可以使用std::removestd::remove_if 删除您想要的项目,而不是自己完成这项工作。请注意,这基本上有点像分区操作——它返回一个迭代器,您想要保留的所有内容都是从范围的开头到该迭代器。您要删除的所有内容都在该迭代器之后,直到您作为输入提供的范围的末尾。

    在这种情况下,您可以按照以下一般顺序执行操作:

    std::deque<int> vals { 1, 2, 3, 4, 5, 6, 7, 8};
    
    // get an iterator one before the end of `vals`
    auto end = vals.end()-1;
    
    // remove the even items in the range (so all except `8`)
    auto pos = std::remove_if(vals.begin(), end, 
        [](int v){ return v %2 == 0;} 
    );
    
    // erase the items we just "removed"
    vals.erase(pos, end);
    
    // show the result
    for (v : vals)
        std::cout << v << ", ";
    

    【讨论】:

    • 不错。这就像一个解决方案一样简单。完美
    【解决方案2】:

    来自std::deque::erase

    所有迭代器和引用都无效,除非被擦除的元素位于容器的末尾或开头,在这种情况下,只有迭代器和对被擦除元素的引用无效。

    这意味着,您不能使用迭代器对双端队列进行迭代并删除一些元素。而是将std::remove_ifstd::deque::erase 一起使用。

    (未经测试,但你会明白的)

    std::deque<T> dq = /* ... */;
    auto from = std::remove_if(dq.begin(), std::prev(dq.end()),
        [](decltype(dq)::const_reference, decltype(dq)::const_reference){ return cond(); }
    );
    dq.erase(from, std::prev(dq.end()));
    

    【讨论】:

    • 这就是为什么我有它 = dq.erase(it) 来自文档:一个迭代器,指向函数调用擦除的最后一个元素之后的元素的新位置。如果操作删除了序列中的最后一个元素,则这是容器结束。
    【解决方案3】:

    这个怎么样:

    deque dq;
    //fill it
    for(int i = 0; i < dq.size() - 1; i++) //notice the "-1" to avoid reaching the last element
    {
        if ( cond() ) 
        {
            dq.erase(dq.begin()+i);
            i--;
        } 
    }
    

    您可以使用operator[] 访问deque 元素,因此dq[i] 是双端队列的元素编号i

    【讨论】:

      【解决方案4】:

      使用it_end.base():

      #include <iostream>
      #include <deque>
      #include <iterator>
      
      using namespace std;
      
      int main()
      {
          deque<int> dq = { 0, 1, 2, 3,4, 5 };
          auto it_end = dq.rbegin(); it_end++;
      
          for (auto it = dq.begin(); it != it_end.base(); ++it) {
              cout << *it << " ";
          }
      
          cout << "\n";
          return 0;
      }
      

      输出:

      0 1 2 3 4
      

      有关 base() 函数如何用于反向迭代器的详细信息,请参阅 https://stackoverflow.com/a/10373912/12711

      【讨论】:

        猜你喜欢
        • 2011-09-19
        • 2018-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-31
        • 2021-02-20
        • 1970-01-01
        • 2011-07-22
        相关资源
        最近更新 更多