是否有类似STL的函数用索引的某些函数填充数组?

问题描述 投票:1回答:5

在C ++中,我们具有std::fillstd::fill_n之类的函数,这些函数是方便的单行方式,将指针数组,向量,std::array和其他容器填充为值。一些容器还具有自己的fill方法,以允许以恒定值进行填充。还有函数std::generate{_n}std::iota,前者允许使用生成器函数填充元素,而后者则用索引填充范围。

我正在寻找的是一种类似的解决方案-最好是一种单线解决方案,并在标准库中定义-允许使用索引的某些功能填充容器。例如,这将是数组的解决方案:

std::array<int, 100> arr;
for (std::size_t i = 0; i < 100; i++)
    arr[i] = f(i);

其中f(std::size_t i)是索引的某些功能。

是否有执行此操作的集成方法?

c++ stl
5个回答
3
投票

您可以使用有状态的lambda:

std::array<int, 100> arr;   
std::generate(arr.begin(), arr.end(), [i = std::size_t(0)]() mutable {return f(i++);});

但是我认为这使代码变得比所需的复杂。使用普通循环可能是最好的选择。


1
投票

如果您始终遍历整个数组,则甚至不必使用任何stl函数,只需使用范围循环:

std::array<int, 100> arr;
int idx = 0;
for (auto& item : array)
    item = f(idx++);

另一种选择是使用for_each(如果将来您想填充数组[[仅部分,这可能会更有用)]

#include <algorithm> std::array<int, 100> arr; int idx = 0; std::for_each(begin(arr), end(arr), [&idx](int &n){ n = f(idx++); });
不幸的是,在两种情况下,您都必须具有单独的索引变量(这里:idx

1
投票
为此考虑编写自己的

STL-like函数模板apply_idx_func()

template<typename FwdItor, typename F> void apply_idx_func(FwdItor first, FwdItor last, F f) { for (size_t idx = 0; first != last; ++first, ++idx) *first = f(idx); }
例如:

auto main() -> int { std::array<int, 10> arr; // just adds 100 to the index auto func = [](size_t idx) -> int { return 100 + idx; }; apply_idx_func(std::begin(arr), std::end(arr), func); for (auto elem: arr) std::cout << elem << ' '; std::cout << '\n'; }

输出为:

100 101 102 103 104 105 106 107 108 109


1
投票
#include <algorithm> size_t i = 0; std::generate_n(arr.begin(),arr.size(),[&i](){return f(i++);});
或者可能分两个步骤:

#include <numeric> std::iota(arr.begin(),arr.end(),0); std::transform(arr.begin(),arr.end(),f);

借助boost,我们可以一步完成此操作:

std::transform( arr.begin(), arr.end(), boost::irange(0,arr.size()), [](const auto& val,const auto& index){return f(index);} );

https://www.boost.org/doc/libs/1_64_0/libs/range/doc/html/range/reference/ranges/irange.html

0
投票
我无法使用编译器尝试此操作,因为找不到C ++ 20范围的编译器,但是一旦编译器实现它们,类似的东西就应该起作用:

std::ranges::transform(std::views::iota{1, arr.size()+1}, arr, f);

或者,如果只需要生成值的序列,只需使用]创建它们的范围

auto const values = std::views::iota{1, arr.size()+1} | std::views::transform(f);

除非您拥有C ++ 20编译器,否则可以使用范围库之一,例如在BoostEric Nieblers ranges-v3
© www.soinside.com 2019 - 2024. All rights reserved.