在一个for循环或range-v3 lib中包含序列的月份



我试着用这样的顺序来取月份:对于一月份,它将以31时间打印1,在二月份将以28时间打印2,等等。

std::vector<int> list = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int count = 0;
for(int k = 0; k < 12; k++){
for(int i = 0; i < list[k]; i++)
cout << count + 1;
count++;
}

list保留一个月的总天数。

我可以这样做for循环,但我想在1循环或range-v3库中做。在range-v3 lib中,我尝试使用accumulate函数,但我不能这样做。

任何想法?

对于range-v3,您可以:

std::array<int, 12> days{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
auto r = days | ranges::view::transform([count = 0](int n) mutable
{
return ranges::view::ints(1, 1 + n)
| ranges::view::transform([count = ++count](int){ return count; });
})
| ranges::view::join;
for (auto e : r) 
std::cout << e << ' ';

演示,

for (int i = 0; i < 12; ++i) {
for (int j = 0; j != days[i]; ++j) {
std::cout << i + 1;
}
}

似乎更清晰。

您可以使用for_eachfill_n

std::ranges::for_each(list, [count = 0](int i) mutable { std::ranges::fill_n(std::ostream_iterator<int>(std::cout, " "), i, ++count); });

您正在寻找的算法是flat_map。range-v3巧妙地隐藏在for_each的名字之下。

基本上,我们有transform(其他一些语言称之为map) -它接受范围T和函数T -> U,并产生范围U。这是一个1-1映射

我们可以将其推广到一个算法,该算法接受范围T和函数T -> range_of<U>,并产生范围U。而transform本身会产生U的范围,我们将结果扁平化。因此,flat_map.

在range-v3中,看起来像:

views::iota(0u, days_in_month.size())
| views::for_each([&](int month){
return views::repeat_n(month+1, days_in_month[month])
})

views::enumerate(days_in_month)
| views::for_each([](auto e){
auto [idx, days] = e;
return views::repeat_n(idx+1, days);
})

演示。

最新更新