I have a collection of values:
auto v = std::vector{43, 1, 3, 2, 4, 6, 7, 8, 19, 101};
Over this collection of values I want to apply a view that follows this criteria:
- First element should always be picked.
- From the next elements, pick only even numbers until ...
- ... finding an element equal or greater than 6.
This is the view I tried:
auto v = std::vector{43, 1, 3, 2, 4, 6, 7, 8, 19, 101};
auto r = v |
std::views::take(1) |
std::views::filter([](const int x) { return !(x & 1); }) |
std::views::take_while([](const int x) { return x < 6; });
for (const auto &x : r)
std::cout << x << ' ';
But the execution don't even enter the print loop because the view is empty. My guess si that all the criteria is applied at once:
- Pick first element (43).
- Is odd number.
- View ends.
What I was expecting:
- Pick first element without checking anything.
- From the rest of elements, filter only even numbers (
2
,4
,6
,8
). - From filtered elements, pick numbers until a number equal to or greater than 6 appears (
2
,4
). 43 2 4
is printed.
How can I build a view over my collection of values that behaves as I was expecting?
CodePudding user response:
With range-v3, you can use views::concat
to concatenate the first element of the range and the remaining filtered elements, for example:
auto v = std::vector{43, 1, 3, 2, 4, 6, 7, 8, 19, 101};
auto r = ranges::views::concat(
v | ranges::views::take(1),
v | ranges::views::drop(1)
| ranges::views::filter([](const int x) { return !(x & 1); })
| ranges::views::take_while([](const int x) { return x < 6; })
);
CodePudding user response:
With only standard C 20, you could do it like this:
bool first = true;
auto r = v |
std::views::filter([first](const int x) { return first || !(x & 1); }) |
std::views::take_while([&first](const int x) { return std::exchange(first, false) || x < 6; });
It first filters on being first element, or being even number.
It then takes while being first (and at the same time sets first to false) or less than 6.
std::exchange
from <utility>
is a very useful, simple function.