我已经制作了一个滚动/环绕项目地图的方法,因此如果到达目的地,该方法将返回第一个项目,反之亦然。
有更简洁的方法吗?
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--;
}
答案 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)
这是一个困难的设计。如果到达“结束”环绕“开始”,你如何表示一个空容器?环绕式思想模拟无限序列或环,但没有办法检测迭代器是否仍然指向有效位置。
这个问题让人联想到在不使用“虚拟条目”的情况下编写可变大小的环形缓冲区(例如队列)的尝试:如何区分空环和完整环?存储基本位置和大小仅适用于随机存取存储(与链接节点相对),并且不像指针或索引对那样适合锁定优化。