C ++将常量添加到向量切片
C++ add constant to slice of vector
我知道 transform
我可以像这样向一些向量添加一个常量:
std::vector<int> a(3, 2);
std::transform( a.begin(), a.end(), a.begin(), std::bind2nd( std::plus<double>(), 1 ) );
我想知道如何修改 transform
以向向量的某些切片 [index:end]
添加常量,例如最后两个元素。
我可以用一个循环来完成,例如:
for (int i=1; i < a.size(); i++) {
a.at(i) += 1;
}
但也许有更好的选择
只是最后 N
个元素?使用反向迭代器:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main() {
std::vector<int> a(3, 2);
std::transform(a.rbegin(), std::next(a.rbegin(), 2), a.rbegin(),
[](auto n) { return n + 1; });
for (auto n : a) {
std::cout << n << '\n';
}
return 0;
}
(如果您出于某种原因需要将 a
更改为没有随机迭代器的容器类型,则使用 std::next()
而不是仅使用 a.rbegin() + 2
会更容易。)
小重构后的相同代码:
std::vector< int > a(3, 2);
auto start = a.begin();
auto end = a.end();
auto func = [](auto val) {
return val + 1;
};
std::transform(start, end, start, func);
现在修改start
和end
的值,只能修改切片
为此std::advance
可以使用:
std::advance(start, 1);
std::advance(end, -1);
在上面的代码中:
start
是开始后的 1 个元素(第 2 个元素 - 索引为 1 的元素)。
end
是从末尾算起 1 个元素。
您可以使用跨度(C++20 中的 std::span
,更早的 gsl::span
)来表示您的切片。如果您不了解跨度,请查看:
所以如果你写,
// ... vector a gets defined
auto slice = std::span(a).subspan(some_index);
切片现在的行为就像任何标准库容器一样。具体来说,你可以这样写:
std::transform(slice.begin(), slice.end(), slice.begin(), [](auto v) { return v + 1; });
算法采用迭代器而不是容器的原因正是针对这种情况。
调整 Python 样式切片的一般方法是将 +ve
值添加到 begin
和 -ve
到 end
。假设至少有两个元素,递增最后两个元素将是
auto start = a.end() - 2;
auto finish = a.end();
std::transform( start, finish , start, std::bind2nd( std::plus<double>(), 1 ) );
我知道 transform
我可以像这样向一些向量添加一个常量:
std::vector<int> a(3, 2);
std::transform( a.begin(), a.end(), a.begin(), std::bind2nd( std::plus<double>(), 1 ) );
我想知道如何修改 transform
以向向量的某些切片 [index:end]
添加常量,例如最后两个元素。
我可以用一个循环来完成,例如:
for (int i=1; i < a.size(); i++) {
a.at(i) += 1;
}
但也许有更好的选择
只是最后 N
个元素?使用反向迭代器:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main() {
std::vector<int> a(3, 2);
std::transform(a.rbegin(), std::next(a.rbegin(), 2), a.rbegin(),
[](auto n) { return n + 1; });
for (auto n : a) {
std::cout << n << '\n';
}
return 0;
}
(如果您出于某种原因需要将 a
更改为没有随机迭代器的容器类型,则使用 std::next()
而不是仅使用 a.rbegin() + 2
会更容易。)
小重构后的相同代码:
std::vector< int > a(3, 2);
auto start = a.begin();
auto end = a.end();
auto func = [](auto val) {
return val + 1;
};
std::transform(start, end, start, func);
现在修改start
和end
的值,只能修改切片
为此std::advance
可以使用:
std::advance(start, 1);
std::advance(end, -1);
在上面的代码中:
start
是开始后的 1 个元素(第 2 个元素 - 索引为 1 的元素)。end
是从末尾算起 1 个元素。
您可以使用跨度(C++20 中的 std::span
,更早的 gsl::span
)来表示您的切片。如果您不了解跨度,请查看:
所以如果你写,
// ... vector a gets defined
auto slice = std::span(a).subspan(some_index);
切片现在的行为就像任何标准库容器一样。具体来说,你可以这样写:
std::transform(slice.begin(), slice.end(), slice.begin(), [](auto v) { return v + 1; });
算法采用迭代器而不是容器的原因正是针对这种情况。
调整 Python 样式切片的一般方法是将 +ve
值添加到 begin
和 -ve
到 end
。假设至少有两个元素,递增最后两个元素将是
auto start = a.end() - 2;
auto finish = a.end();
std::transform( start, finish , start, std::bind2nd( std::plus<double>(), 1 ) );