Reputation: 511
In C++ I can use reverse_iterator
to loop elements of container, say, list
, backwards.
How do I iterate over a certain number of elements? Not reaching the beginning? This code works, but I feel there is a better way.
std::list<int> mylist{1,2,3,4,5};
int cnt = 3;
for (auto rit = mylist.rbegin(); rit != mylist.rend(); ++rit) {
if (cnt == 0) break;
std::cout << *rit << " ";
--cnt;
}
Expected output {5, 4, 3}
.
Upvotes: 1
Views: 411
Reputation: 38325
You can adjust the loop as follows:
for (auto rit = mylist.rbegin(); rit != std::next(mylist.rbegin(), 3); ++rit)
{
std::cout << *rit << " ";
}
but note that for this to work reliably, you need to check that the list is at least of size 3 or adjust the parameter to std::next
as in const auto n = std::min<std::size_t>(3, mylist.size());
.
With C++20, you should be able to go with (obviously not tested)
#include <ranges>
for (int n : mylist | std::ranges::reverse_view | std::ranges::take_view(3))
std::cout << n << "\n";
This renders the size testing superfluous, as take_view
is bound by the range size (it performs this check internally).
Upvotes: 4
Reputation: 123431
I would not put incrementing/decrementing and checking the condition in the loop body, but rather put it where you most expect it:
std::list<int> mylist{1,2,3,4,5};
int cnt = 3;
for (auto rit = mylist.rbegin(); rit != mylist.rend() && cnt > 0; ++rit,--cnt) {
std::cout << *rit << " ";
}
Now you could for example add a continue
anywhere in the loop body without making the loop go havoc.
PS: actually I like the other answers better, but I'll leave this one as it is minimal changes and imho incrementing / checking a loop counter inside the loop body is something to be avoided if possible (and it is possible here).
Upvotes: 2
Reputation: 173024
Not reaching the beginning?
If you can guarantee that, then
std::copy_n(mylist.rbegin(), 3, std::ostream_iterator<int>(std::cout, " "));
Or to be safer
std::copy_n(mylist.rbegin(), std::min(mylist.size(), std::list<int>::size_type(3)), std::ostream_iterator<int>(std::cout, " "));
Upvotes: 4