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

发布于 2024-08-14 01:46:56 字数 359 浏览 2 评论 0原文

我创建了一种方法来滚动/环绕项目地图,这样如果到达末尾,该方法将返回第一个项目,反之亦然。

有更简洁的方法吗?

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

}

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

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

莳間冲淡了誓言ζ 2024-08-21 01:46:56

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

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

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.

仙女山的月亮 2024-08-21 01:46:56

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

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

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;
}
倒带 2024-08-21 01:46:56

您可以使用upper_boundlower_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”,其行为也会有所不同。它将从钥匙所在的地方开始,而不是走到结束或开始。

You can use upper_bound and lower_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. It will take up from where the key would have been rather than going to the end or the beginning.

命硬 2024-08-21 01:46:56

您可以实现循环迭代器

You could implement a cyclical iterator.

懵少女 2024-08-21 01:46:56

这是一个困难的设计。如果到达“结束”又回到“开始”,那么如何表示一个空容器?环绕思想对无限序列或环进行建模,但没有方法来检测迭代器是否仍然指向有效位置。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文