使用 foreach 语法迭代时如何检查我是否在最后一个元素上
How can I check if I'm on the last element when iterating using foreach syntax
例如:
for( auto &iter: item_vector ) {
if(not_on_the_last_element) printf(", ");
}
或
for( auto &iter: skill_level_map ) {
if(not_on_the_last_element) printf(", ");
}
你真的不能。这就是范围的意义所在,你不需要迭代器。但是,如果不是第一个,您可以更改有关如何打印逗号的逻辑来打印它:
bool first = true;
for (auto& elem : item_vector) {
if (!first) printf(", ");
// print elem
first = false;
}
如果这是循环的意图。或者您可以比较地址:
for (auto& elem : item_vector) {
if (&elem != &item_vector.back()) printf(", ");
// ...
}
没有很好的方法。但是,如果我们可以轻松访问容器的最后一个元素......
std::vector<int> item_vector = ...;
for (auto & elem : item_vector) {
...
if (&elem != &item_vector.back())
printf(", ");
}
这些类型的循环最好使用">循环半"结构编写:
#include <iostream>
#include <vector>
int main()
{
auto somelist = std::vector<int>{1,2,3,4,5,6,6,7,8,9,6};
auto first = begin(somelist), last = end(somelist);
if (first != last) { // initial check
while (true) {
std::cout << *first++;
if (first == last) break; // check in the middle
std::cout << ", ";
}
}
}
打印的实时示例
1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 6
即在最后一个元素的末尾没有分隔符。
中间的检查使它与 do-while (预先检查(或for_each/基于范围(在最后检查(不同。尝试在这些循环上强制常规 for 循环将引入额外的条件分支或重复的程序逻辑。
这
就像一个状态模式。
#include <iostream>
#include <vector>
#include <functional>
int main() {
std::vector<int> example = {1,2,3,4,5};
typedef std::function<void(void)> Call;
Call f = [](){};
Call printComma = [](){ std::cout << ", "; };
Call noPrint = [&](){ f=printComma; };
f = noPrint;
for(const auto& e:example){
f();
std::cout << e;
}
return 0;
}
Output:
1, 2, 3, 4, 5
第一次通过f
指向noPrint
,这只能使f
然后指向printComma
,因此逗号仅在第二个和后续项目之前打印。
将此
代码安全地存储在小实用程序袋中的头文件中:
namespace detail {
template<class Iter>
struct sequence_emitter
{
sequence_emitter(Iter first, Iter last, std::string sep)
: _first(std::move(first))
, _last(std::move(last))
, _sep(std::move(sep))
{}
void write(std::ostream& os) const {
bool first_element = true;
for (auto current = _first ; current != _last ; ++current, first_element = false)
{
if (!first_element)
os << _sep;
os << *current;
}
}
private:
Iter _first, _last;
std::string _sep;
};
template<class Iter>
std::ostream& operator<<(std::ostream& os, const sequence_emitter<Iter>& se) {
se.write(os);
return os;
}
}
template<class Iter>
detail::sequence_emitter<Iter>
emit_sequence(Iter first, Iter last, std::string separator = ", ")
{
return detail::sequence_emitter<Iter>(std::move(first), std::move(last), std::move(separator));
}
然后,您可以发出任何容器的任何范围,而无需尾随分隔符,如下所示:
vector<int> x { 0, 1, 2, 3, 4, 5 };
cout << emit_sequence(begin(x), end(x)) << endl;
set<string> s { "foo", "bar", "baz" };
cout << emit_sequence(begin(s), end(s), " comes before ") << endl;
预期输出:
0, 1, 2, 3, 4, 5
bar comes before baz comes before foo
基于范围的 for 循环用于迭代整个范围。如果你不想这样,你为什么不做一个常规的 for 循环呢?
auto end = vector.end() - 1;
for (auto iter = vector.begin(); iter != end; ++iter) {
// do your thing
printf(", ");
}
// do your thing for the last element
如果您不想像我一样重复两次代码来"做你的事",那么创建一个 lambda 来调用它:
auto end = vector.end() - 1;
// create lambda
for (auto iter = vector.begin(); iter != end; ++iter) {
lambda(*iter);
printf(", ");
}
lambda(vector.back());
相关文章:
- 测试迭代器是否位于列表中的最后一个
- 如何知道地图中的最后一个元素是否被删除?
- 这种获取模板参数包中最后一个元素的方法是否有隐藏的开销?
- 如何检查字符串中的最后一个字符是否是某个字符并将其从字符串中删除?(C++)
- 如果地图擦除范围内的第一个和最后一个相等,则是否删除该元素
- C++的最后一个位置是否有计算单元的标准功能
- 正则表达式匹配是否保证始终只关注最后一个模式?C++
- 检查当前元素是否是集合的最后一个元素
- C 是否有办法仅返回for循环的最后一个实例
- 检查最后一个项目是否通过地图密钥存在
- 如何使用 for(int i:myVector) 代码样式知道元素是否是矢量中的最后一个元素
- 我是否应该将最后一个“返回”语句封装为“else { return .. }',如果它在逻辑上是可选的
- 我读了map.erase(map.end());删除地图的最后一个元素。但是最后一个元素是什么?它是否基于元素的插入顺序?
- 使用 foreach 语法迭代时如何检查我是否在最后一个元素上
- 是否有任何 pthread 函数可以在最后一个线程终止时调用某些内容
- 是否可以删除链接列表中的最后一个节点
- 检测迭代器是否是std::map的最后一个元素
- 在c++中,如何确定一个类是否是继承链中的最后一个类/子类?它位于基类的另一端
- 是否存在仅包含第一个值和最后一个值的c++容器?
- 是否有办法找出哪个线程接收了最后一个输入