C++ 向后迭代容器 N 步
C++ iterate container backwards N steps
在 C++ 中,我可以使用 reverse_iterator
向后循环容器元素,例如 list
。
如何遍历一定数量的元素?没有到达起点?此代码有效,但我觉得有更好的方法。
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;
}
预期输出 {5, 4, 3}
。
您可以按如下方式调整循环:
for (auto rit = mylist.rbegin(); rit != std::next(mylist.rbegin(), 3); ++rit)
{
std::cout << *rit << " ";
}
但请注意,为了使其可靠地工作,您需要检查列表的大小是否至少为 3 或将参数调整为 std::next
,如 const auto n = std::min<std::size_t>(3, mylist.size());
.
使用 C++20,您应该可以使用(显然未测试)
#include <ranges>
for (int n : mylist | std::ranges::reverse_view | std::ranges::take_view(3))
std::cout << n << "\n";
这使得大小测试变得多余,因为 take_view
受范围大小的限制(它在内部执行此检查)。
我不会将 incrementing/decrementing 和检查条件放在循环体中,而是将其放在您最期望的位置:
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 << " ";
}
例如,现在您可以在循环体的任何位置添加一个 continue
而不会破坏循环。
PS:实际上我更喜欢其他答案,但我会留下这个,因为它的变化很小,恕我直言,如果可能的话,应该避免在循环体内递增/检查循环计数器(这里是可能的)。
Not reaching the beginning?
如果你能保证,那么
std::copy_n(mylist.rbegin(), 3, std::ostream_iterator<int>(std::cout, " "));
或者更安全
std::copy_n(mylist.rbegin(), std::min(mylist.size(), std::list<int>::size_type(3)), std::ostream_iterator<int>(std::cout, " "));
在 C++ 中,我可以使用 reverse_iterator
向后循环容器元素,例如 list
。
如何遍历一定数量的元素?没有到达起点?此代码有效,但我觉得有更好的方法。
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;
}
预期输出 {5, 4, 3}
。
您可以按如下方式调整循环:
for (auto rit = mylist.rbegin(); rit != std::next(mylist.rbegin(), 3); ++rit)
{
std::cout << *rit << " ";
}
但请注意,为了使其可靠地工作,您需要检查列表的大小是否至少为 3 或将参数调整为 std::next
,如 const auto n = std::min<std::size_t>(3, mylist.size());
.
使用 C++20,您应该可以使用(显然未测试)
#include <ranges>
for (int n : mylist | std::ranges::reverse_view | std::ranges::take_view(3))
std::cout << n << "\n";
这使得大小测试变得多余,因为 take_view
受范围大小的限制(它在内部执行此检查)。
我不会将 incrementing/decrementing 和检查条件放在循环体中,而是将其放在您最期望的位置:
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 << " ";
}
例如,现在您可以在循环体的任何位置添加一个 continue
而不会破坏循环。
PS:实际上我更喜欢其他答案,但我会留下这个,因为它的变化很小,恕我直言,如果可能的话,应该避免在循环体内递增/检查循环计数器(这里是可能的)。
Not reaching the beginning?
如果你能保证,那么
std::copy_n(mylist.rbegin(), 3, std::ostream_iterator<int>(std::cout, " "));
或者更安全
std::copy_n(mylist.rbegin(), std::min(mylist.size(), std::list<int>::size_type(3)), std::ostream_iterator<int>(std::cout, " "));