简体   繁体   English

C ++滚动浏览stl :: map中的项目

[英]C++ “Scrolling” through items in an stl::map

I've made a method to scroll/wrap around a map of items, so that if the end is reached, the method returns the first item and vice-versa. 我已经制作了一种在项目地图上滚动/环绕的方法,这样,如果到达终点,该方法将返回第一个项目,反之亦然。

Is there more succinct way of doing this? 有更简洁的方法吗?

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--;

}

You could implement the wrap-around behavior directly into a new iterator-class - templated to be a wrapper for some actual iterator, that supplies a more elegant interface to the caller (so that its increment and decrement operators do the wrap-around automatically). 您可以将环绕行为直接实现到新的迭代器类中-模板化为一些实际迭代器的包装器,该包装器为调用者提供了更优雅的接口(以便其增量和减量运算符自动进行环绕) 。

Also - be careful of the empty container. 另外-小心空的容器。 You don't want to "wrap-around" when there are no elements in the container. 当容器中没有元素时,您不想“包装”。

You can use upper_bound and lower_bound . 您可以使用upper_boundlower_bound For example: 例如:

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;
}

This will also behave differently if "myKey" doesn't exist in the map. 如果“ myKey”在地图中不存在,这也将表现不同。 It will take up from where the key would have been rather than going to the end or the beginning. 它将从键本来应该占据的地方开始,而不是从头到尾。

You can do this with a template. 您可以使用模板执行此操作。 As was stated by a previous poster, this can be cumbersome from the standpoint that it never reaches the end so the user must somehow control this. 如先前的海报所述,从永远到达终点的角度来看,这可能很麻烦,因此用户必须以某种方式控制它。 I'm assuming you have a good reason, perhaps producing some round robin behavior. 我假设您有充分的理由,也许会产生一些轮循行为。

#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;
}

您可以实现一个循环迭代器

This is a difficult design. 这是一个困难的设计。 If reaching the "end" wraps around to the "beginning", how do you represent an empty container? 如果到达“末尾”将环绕到“开始”,那么您如何表示一个空容器? The wraparound idea models an infinite sequence or a ring, but without a means to detect whether the iterator is still pointing to a valid position. 环绕式想法为无限序列或环建模,但没有检测迭代器是否仍指向有效位置的方法。

This problem is reminiscent of attempts to write a variable-sized ring buffer (such as a queue) without using a "dummy entry": How does one distinguish an empty ring from a full ring? 此问题使人想起尝试在不使用“虚拟条目”的情况下写入可变大小的环形缓冲区(例如队列)的方法:如何区分空环和满环? Storing a base position and a size is only appropriate for random-access storage (as opposed to linked nodes), and is less amenable to locking optimization than pointer or index pairs. 存储基本位置和大小仅适用于随机存取存储(与链接的节点相对),并且比指针或索引对更不适合锁定优化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM