C ++“滚动”stl :: map中的项目

时间:2009-12-07 23:20:36

标签: c++ stl map iterator

我已经制作了一个滚动/环绕项目地图的方法,因此如果到达目的地,该方法将返回第一个项目,反之亦然。

有更简洁的方法吗?

MyMap::const_iterator it = myMap.find(myKey);

if (it == myMap.end())
    return 0;

if (forward) {

    it++;

    if (it == myMap.end()) {
        it = myMap.begin();
    }

} else {

    if (it == myMap.begin()) {
        it = myMap.end();
    }

    it--;

}

5 个答案:

答案 0 :(得分:5)

你可以将环绕行为直接实现到一个新的迭代器类中 - 模板化为一些实际迭代器的包装器,它为调用者提供了一个更优雅的接口(以便它的递增和递减运算符执行包装 - 自动周围)。

另外 - 小心空容器。当容器中没有元素时,您不希望“环绕”。

答案 1 :(得分:1)

您可以使用 upper_bound lower_bound 。例如:

if (myMap.empty()) return 0;

MyMap::const_iterator it;

if (forward) {
    it = myMap.upper_bound(myKey);
    if (it == myMap.end()) it = myMap.begin();
} else {
    it = myMap.lower_bound(myKey);
    if (it == myMap.begin()) it = myMap.end();
    --it;
}

如果地图中不存在“myKey”,则表现也会有所不同。它将从密钥所在的位置开始,而不是直到结束或开始。

答案 2 :(得分:1)

您可以使用模板执行此操作。正如之前的一张海报所说,从永远不会达到目的的角度来看,这可能很麻烦,因此用户必须以某种方式控制它。我假设你有充分的理由,也许会产生一些循环行为。

#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <map>

using namespace std;

template <class T>
class ScrollIterator
{
public:
    ScrollIterator(T &myCtr, typename T::iterator pos)
        :ctr(myCtr),
         it(pos)
    {

    }

    ScrollIterator operator++()
    {
        if (++it == ctr.end()) { it = ctr.begin(); }
        return *this;
    }

    bool operator!=(const ScrollIterator &rhs) const
    {
        return (this->it != rhs.it);
    }

    bool operator!=(const typename T::const_iterator &rhsIT) const
    {
        return (this->it != rhsIT);
    }

    typename T::value_type operator*() const
    {
        return *it;
    }

private:
    T &ctr;
    typename T::iterator it;
};


int main (int argc, char *argv[])
{
    vector<int> v;
    v.push_back(2);
    v.push_back(3);
    v.push_back(5);
    v.push_back(7);

    int i = 0;
    for (ScrollIterator<vector<int> > it(v,v.begin()); it != v.end() && i < 10; ++i, ++it)
    {
        cout << "Vector = " << i << " Value: " << *it << "\n";
    }

    set<string> s;
    s.insert("c");
    s.insert("a");
    s.insert("b");

    i = 0;
    for (ScrollIterator<set<string> > it(s,s.begin()); it != s.end() && i < 10; ++i, ++it)
    {
        cout << "Set = " << i << " Value: " << *it << "\n";
    }

    map<string, int> y;
    y["z"] = 10;
    y["y"] = 20;
    y["x"] = 30;

    i = 0;
    for (ScrollIterator<map<string, int> > it(y,y.begin()); it != y.end() && i < 10; ++i, ++it)
    {
        cout << "Map = " << i << " Iterator: " << (*it).first << " = " << (*it).second << "\n";
    }

    return 1;
}

答案 3 :(得分:1)

您可以实施cyclical iterator

答案 4 :(得分:0)

这是一个困难的设计。如果到达“结束”环绕“开始”,你如何表示一个空容器?环绕式思想模拟无限序列或环,但没有办法检测迭代器是否仍然指向有效位置。

这个问题让人联想到在不使用“虚拟条目”的情况下编写可变大小的环形缓冲区(例如队列)的尝试:如何区分空环和完整环?存储基本位置和大小仅适用于随机存取存储(与链接节点相对),并且不像指针或索引对那样适合锁定优化。