提问人:RAM 提问时间:11/18/2023 最后编辑:Jarod42RAM 更新时间:11/18/2023 访问量:115
如何遍历 std::vector 的范围
How to iterate over ranges of a std::vector
问:
我有一个关于使用 C++11 或 C++14 迭代向量切片/范围的最佳方法是什么的问题。假设我们有一个包含一堆值的:std::vector
std::vector<int> v = {0,1,2,3,4,5,6,7,8,9,10};
此向量用作输入,以根据连续值计算值,其操作类似于移动平均线。为此,我有一个函数,该函数将连续元素作为输入,进行一些数学运算,并输出一个值。这意味着此函数类似于以下声明:n
foo
n
int foo(const std::vector<int> &v_range);
我想应用于所有元素,将它们映射到另一个向量。
我可以通过遍历向量,提取子向量并将其传递给 .请参阅下面的代码。foo
v
foo
// Example program
#include <vector>
#include <iostream>
int foo(const std::vector<int> &v) {
std::cout << "[";
for(int e: v) {
std::cout << e << ",";
}
std::cout << "]" << std::endl;
return 0;
}
int main()
{
std::vector<int> v = {0,1,2,3,4,5,6,7,8,9,10};
std::vector<int> v_out;
std::vector<int> v = {0,1,2,3,4,5,6,7,8,9,10};
std::vector<int> v_out;
const int n = 3;
for (auto begin = v.begin(), end = std::next(v.begin(), n);
std::next(begin, n - 1) != v.end();
++begin, ++end) {
std::vector<int> v_slice(begin, end);
v_out.push_back(foo(v_slice));
}
}
上述方法有效,但它不仅需要大量样板代码,而且还不必要地复制元素。
我想知道 C++ 是否提供了任何巧妙的方法来轻松迭代向量元素的切片/范围,这些元素可以传递给 或 。std::transform
std::for_each
或者,我想知道 C++ 是否提供了任何将输入向量转换为向量范围向量的方法,类似于以下伪代码:
std::vector<int> v = {0,1,2,3,4,5,6,7,8,9,10};
std::vector<std::vector<int>> v_sliced = {
{0,1,2},
{1,2,3},
{2,3,4}
///...
{8,9,10}
};
欢迎任何意见。
答:
1赞
Jarod42
11/18/2023
#1
有了 ,您可能有:std::transform
std::vector<std::vector<int>>
std::vector<std::vector<int>> sliced_n(const std::vector<int>& v, std::size_t n)
{
if (v.size() < n) throw std::invalid_argument("");
std::vector<std::vector<int>> res;
std::transform(v.begin(), v.end() - n + 1,
std::back_inserter(res),
[n](auto &e){ return std::vector(&e, &e + n); });
return res;
}
int main()
{
std::vector<int> v = {0,1,2,3,4,5,6,7,8,9,10};
auto sliced = sliced_n(v, 3);
std::vector<int> v_out;
std::transform(sliced.begin(), sliced.end(),
std::back_inserter(v_out),
[](const auto& v){ return foo(v); });
}
但更简单
std::transform(v.begin(), v.end() + 1 - n,
std::back_inserter(v_out),
[&](const auto& e){ return foo(std::vector(&e, &e + n)); });
评论
0赞
RAM
11/18/2023
如前所述,您的示例已损坏,因为它无法遍历。{8,9,10}
0赞
Jarod42
11/18/2023
偏移固定...
评论
foo
std::span
end++ != v.end()
-v.end()++
是UBint foo(std::vector<int>::iterator begin, std::vector<int>::iterator end);
v_slice