向量子集的迭代器
Iterator for a subset of a vector
是否可以从一个vector中得到一个const迭代器,这个vector在失效前只能迭代一定范围的vector?
例如,如果我有一个包含 10 个元素的向量,我想 return 一个包含 4 到 7 个元素的迭代器。
伪代码:
int main()
{
std::vector<int> vector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
auto iterator = GetRangedIterator(vector, 4, 7)
for (const int& num : iterator)
print num; // 4, 5, 6, 7
}
标准库中没有任何内容可以明确执行此操作,但如果您愿意使用 Boost,则可以使用以下使用 range
概念的方法:
auto range = boost::make_iterator_range(v.begin()+3, v.begin()+7);
BOOST_FOREACH(int i, range)
{
cout << i << endl;
}
这应该输出 4567
这很简单(尽管我将结果称为范围,而不是迭代器)。
一个简单的实现看起来像这样:
template <class Iter>
class range {
Iter b;
Iter e;
public:
range(Iter b, Iter e) : b(b), e(e) {}
Iter begin() { return b; }
Iter end() { return e; }
};
template <class Container>
range<typename Container::iterator>
make_range(Container& c, size_t b, size_t e) {
return range<typename Container::iterator> (c.begin()+b, c.begin()+e);
}
就目前而言,这遵循正常的 C++ 约定(从 0 开始计数,您指定的结束超出范围的结束,而不是在范围内)所以要获得您要求的输出,您需要指定 3, 7
的范围,例如:
for (int num : make_range(vector, 3, 7))
std::cout << num << ", "; // 4, 5, 6, 7,
请注意,基于范围的 for
循环知道如何使用 begin
和 end
成员函数来告诉它要迭代的范围,所以我们没有要处理无效的迭代器或类似的东西,我们只需要指定我们关心的范围的开始和结束。
您可以使用 range-v3 library that is the bases of a Ranges TS which will been part of C++20,但该库已经适用于 C++11 编译器。方法如下:
#include <range/v3/all.hpp>
#include <iostream>
#include <vector>
int main()
{
using namespace ranges;
auto v = view::iota(1, 11) | to_<std::vector<int>>();
std::cout << view::all(v) << '\n';
auto rng = v | view::slice(3, 7);
std::cout << rng << '\n';
}
你可以用这个
for( it = v1.begin() + a; it <= v1.begin() + b; it++ )
下面的代码是一个小演示
#include <vector>
#include <iostream>
using namespace std;
int main(){
vector<int> v1;
for( int i = 0; i < 50; i++ ){
v1.push_back( 2*(i+1) );
cout<<v1.at(i)<<" ";
}
cout<<endl;
vector<int>::iterator it;
int a = 5;
int b = 9;
for( it = v1.begin() + a; it <= v1.begin() + b; it++ ){
cout<<(*it)<<" ";
}
cout<<endl;
}
输出为
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100
12 14 16 18 20
您可以使用 :
auto first_index = 3;
auto last_index = 6;
auto count = last_index - first_index + 1;
auto interesting_nums = gsl::make_span(std::cbegin(vector) + start_index, count);
for(auto& num : interesting_nums) { /* do stuff */ }
备注:
- 在您的示例中,您得到了第 4 到第 7 个元素,即索引 3 到 6,这是我在这里使用的。
- 这段代码应该适用于任何容器,而不仅仅是矢量。
- spans 是 GSL 的一部分,支持库为 C++ Core Guidelines。他们可能会在2020年正式进入C++标准,并受到社区的好评。
是否可以从一个vector中得到一个const迭代器,这个vector在失效前只能迭代一定范围的vector?
例如,如果我有一个包含 10 个元素的向量,我想 return 一个包含 4 到 7 个元素的迭代器。
伪代码:
int main()
{
std::vector<int> vector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
auto iterator = GetRangedIterator(vector, 4, 7)
for (const int& num : iterator)
print num; // 4, 5, 6, 7
}
标准库中没有任何内容可以明确执行此操作,但如果您愿意使用 Boost,则可以使用以下使用 range
概念的方法:
auto range = boost::make_iterator_range(v.begin()+3, v.begin()+7);
BOOST_FOREACH(int i, range)
{
cout << i << endl;
}
这应该输出 4567
这很简单(尽管我将结果称为范围,而不是迭代器)。
一个简单的实现看起来像这样:
template <class Iter>
class range {
Iter b;
Iter e;
public:
range(Iter b, Iter e) : b(b), e(e) {}
Iter begin() { return b; }
Iter end() { return e; }
};
template <class Container>
range<typename Container::iterator>
make_range(Container& c, size_t b, size_t e) {
return range<typename Container::iterator> (c.begin()+b, c.begin()+e);
}
就目前而言,这遵循正常的 C++ 约定(从 0 开始计数,您指定的结束超出范围的结束,而不是在范围内)所以要获得您要求的输出,您需要指定 3, 7
的范围,例如:
for (int num : make_range(vector, 3, 7))
std::cout << num << ", "; // 4, 5, 6, 7,
请注意,基于范围的 for
循环知道如何使用 begin
和 end
成员函数来告诉它要迭代的范围,所以我们没有要处理无效的迭代器或类似的东西,我们只需要指定我们关心的范围的开始和结束。
您可以使用 range-v3 library that is the bases of a Ranges TS which will been part of C++20,但该库已经适用于 C++11 编译器。方法如下:
#include <range/v3/all.hpp>
#include <iostream>
#include <vector>
int main()
{
using namespace ranges;
auto v = view::iota(1, 11) | to_<std::vector<int>>();
std::cout << view::all(v) << '\n';
auto rng = v | view::slice(3, 7);
std::cout << rng << '\n';
}
你可以用这个
for( it = v1.begin() + a; it <= v1.begin() + b; it++ )
下面的代码是一个小演示
#include <vector>
#include <iostream>
using namespace std;
int main(){
vector<int> v1;
for( int i = 0; i < 50; i++ ){
v1.push_back( 2*(i+1) );
cout<<v1.at(i)<<" ";
}
cout<<endl;
vector<int>::iterator it;
int a = 5;
int b = 9;
for( it = v1.begin() + a; it <= v1.begin() + b; it++ ){
cout<<(*it)<<" ";
}
cout<<endl;
}
输出为
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100
12 14 16 18 20
您可以使用
auto first_index = 3;
auto last_index = 6;
auto count = last_index - first_index + 1;
auto interesting_nums = gsl::make_span(std::cbegin(vector) + start_index, count);
for(auto& num : interesting_nums) { /* do stuff */ }
备注:
- 在您的示例中,您得到了第 4 到第 7 个元素,即索引 3 到 6,这是我在这里使用的。
- 这段代码应该适用于任何容器,而不仅仅是矢量。
- spans 是 GSL 的一部分,支持库为 C++ Core Guidelines。他们可能会在2020年正式进入C++标准,并受到社区的好评。