【问题标题】:Check if iterator to std::map points to second last element检查 std::map 的迭代器是否指向倒数第二个元素
【发布时间】:2016-10-31 00:02:28
【问题描述】:

我正在(前向)迭代一个 std::map 并想知道迭代器是否指向 倒数第二个 元素。我似乎无法在任何地方找到如何做到这一点。

我有:

bool
isSecondLastFile(const TDateFileInfoMap::const_iterator &tsFile)
{
    TDateFileInfoMap::reverse_iterator secondLastIt = mFileInfoMap.rbegin()  + 1;
    return (tsFile == secondLastIt);
}

TDateFileInfoMap 是 std::map

我明白了:

error: no match for ‘operator==’ in ‘tsFile == secondLastIt’
/usr/lib/gcc/i686-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_tree.h:287: note: candidates are: bool std::_Rb_tree_const_iterator<_Tp>::operator==(const std::_Rb_tree_const_iterator<_Tp>&) const [with _Tp = std::pair<const long int, TFileInfo>]

这是否意味着我无法比较正向和反向迭代器?

如何判断前向迭代器是否指向倒数第二个元素?

【问题讨论】:

  • tsFile + 2 == mFileInfoMap.end() 怎么样?

标签: c++ dictionary iterator stdmap reverse-iterator


【解决方案1】:

假设您有一个名称为 s 的集合。

s= {s1,s2,...,sN-1, sN} 现在要从 s1.. 迭代到 sN-1(倒数第二个元素),我们将使用 STL 函数 s.begin() 和 s.end()。

end = s.end(); //end指向end

end--// sN的端点

现在在 for 循环中,当 itr(从 set 的开头开始)等于 sN 时,循环将中断,您将在循环内得到 s1,s2,..sN-1。

map<int,int> s;

// to iterate till fixed range in map

auto end =s.end();
end--; // end to second last;

for(auto itr = s.begin(); itr!=end;itr++){
  // do your operation
}

【讨论】:

  • 请添加一些关于此代码如何解决问题的说明
【解决方案2】:

前向迭代器的简单解决方案:

template <typename ForwardIterator>
inline bool isNthLast(std::size_t n, ForwardIterator pos, ForwardIterator last) {
    for( ;; --n, ++pos) {
        if(n == 0) 
            return (pos == last);
        if(pos == last)
            return false;
    }
}

bool isSecondLastFile(TDateFileInfoMap::const_iterator sFile) {
    return isNthLast(2, sFile, mFileInfoMap.end());
}

【讨论】:

    【解决方案3】:

    这是否意味着我无法比较正向和反向迭代器?

    是的,你不能直接比较它们。

    您可以使用base() 获取底层基础迭代器。

    返回底层基础迭代器。那是 std::reverse_iterator(it).base() == it.

    基迭代器指的是下一个元素(从 std::reverse_iterator::iterator_typeperspective) 到元素 reverse_iterator 当前指向。那是&amp;*(rit.base() - 1) == &amp;*rit

    例如

    return (tsFile == (++secondLastIt).base());
    

    顺便说一句:mFileInfoMap.rbegin() + 1 不会编译,因为std::map 的迭代器不是RandomAccessIterator。你可以写:

    TDateFileInfoMap::reverse_iterator secondLastIt = mFileInfoMap.rbegin();
    ++secondLastIt;
    

    请注意,我们不会检查地图是否为空或只有一个元素。

    【讨论】:

    • 这样做似乎返回了最后一个元素,而不是倒数第二个。但是看看 base() 的定义,我不确定为什么会这样......
    • @Danny Here是关于反向迭代器的解释。
    【解决方案4】:

    std::map's 迭代器类型为BidirectionalIterator。只需将 end 迭代器递减两次——首先获取最后一个元素,因为 m.end() 在结束位置之后返回一个迭代器,然后再次获取倒数第二个元素:

    auto penultimate = std::prev(m.end(), 2);
    

    然后你可以简单地检查结果迭代器是否相等:

    auto it = m.begin();
    it == penultimate;
    

    see it live on Coliru

    当然,如果程序中的其他逻辑不能保证地图两个元素,你应该首先检查它。

    【讨论】:

    • 连续的operator-- 难以阅读。为什么不使用auto back = std::prev(m.end(), 2)
    • @KABoissonneault 因为我没想到。谢谢,已修复。
    猜你喜欢
    • 1970-01-01
    • 2016-02-12
    • 2016-03-01
    • 2011-09-19
    • 2018-12-15
    • 1970-01-01
    • 2019-07-23
    • 2018-01-07
    • 2014-06-14
    相关资源
    最近更新 更多