从第 n 个元素开始迭代向量
Start iterating vector from the nth element
我正在尝试从 nth 元素开始迭代一个向量。不确定我应该怎么做。
我有一个向量 A 和 B。我的矢量 A 有 10 个元素 PC1-PC10 我的矢量 B 有 20 个元素 用户1-用户20.
所以我想做的是当我的向量 A 和 B 都到达第 10 个元素时,意思是说向量 [= 的最后一个元素21=]A,我想重复迭代向量 A 但从第 11 开始迭代向量 B 元素,以便我可以用它做一些事情。
下面是我想出的简化代码,但从技术上讲它是一样的:
vector<string>::iterator b = vecB.begin();
for (int i = 1; i < 2; i++) {
for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; a++) {
if (a == vecA.end()) {
b = vecB.begin() + 10; //here the iterator for verB should start from the 11th element
}
++b
}
}
我应该弄乱向量 B 的迭代器吗?或者有其他选择吗?
编辑
看来我终究是问错了问题。我已经标记了这个问题的答案,很快就会发布另一个。感谢您对我的问题的快速回复!
您无需更改 B 的迭代器,它会自动从第 11 个元素继续。但是您需要在 for 循环开始时在 A 上重新开始迭代(或者您将使用 a.end()
这不是有效元素):
if (a == vecA.end()) {
a = vecA.begin();
}
您还应该遍历两者,但只检查 b
上的结束;如果您检查 a
,for
将在 if
变为真之前结束:
for (auto a = vecA.begin(), b = vecB.begin(); b != vecB.end(); ++a, ++b)
你可以看到完整的代码here。
嵌套循环内的if
条件永远不会为真,因为它与循环条件冲突:
for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; a++) {
// This check ----------------------------------^^^^^^^^^^^^^^^
// guarantees that this will never succeed:
// vvvvvvvvvvvvvvv
if (a == vecA.end()) {
...
}
}
你应该像这样重写代码:
vector<string>::iterator b = vecB.begin();
// Check that vecB has sufficient number of elements before entering the loop.
for (int i = 1 ; i < 2 ; i++) {
for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; ++a, ++b) {
...
}
// At this point we know for sure that a == vecA.end(),
// because it is a post-condition of the for loop above.
b = std::next(vecB.begin(), 11);
}
++b
的调用可以移到循环头中。
注意std::next
的用法:虽然
b = vecB.begin() + 10;
针对向量进行编译,不保证对所有类型的容器都适用。使用 std::next
代替:
b = std::next(vecB.begin(), 11);
注意: 此代码假设 vecB
至少比 vecA
多 11 个元素。如果您在进入循环之前检查该假设,这可能没问题。如果这个假设被打破,代码将有未定义的行为。
除了使用std::next
,如@dasblinkenlight的回答所示,还可以使用std::advance
.
b = vecB.begin();
std::advance(b, 10);
我实际上更喜欢手动迭代 C++11 之前的向量,因为它看起来比 iterators
:
更清晰、更易读
for (unsigned int i = 0; i < my_vector.size(); i++) {
my_vector[i]; //Do Something
}
您可以简单地通过修改 for 循环条件(即 unsigned int i = n
)来指定要迭代的范围
编辑:在投票之前实际上阅读了我的整个答案。在向量上使用迭代器过于冗长并且使您的代码几乎不可读。如果有正当理由不应使用此方法来支持迭代器,请发表评论。
大多数人并不是在寻找超通用的、可放入任何容器的解决方案。大多数人都知道他们需要一个动态列表,vector
符合要求,那么为什么不让您的代码易于下一个人阅读呢?
其他人已经回答了如何重置或推进迭代器,所以我只回答,如何以更简单的方式解决您的问题。使用索引而不是两个迭代器并行迭代两个向量要简单得多:
// assumes vecB is bigger than vecA as described in the question
for (std::size_t i = 0; i < vecB.size(); i++) {
auto user = vecB[i];
auto pc = vecA[i % vecA.size()];
}
注意较小的向量是如何使用余数运算符迭代的。
我正在尝试从 nth 元素开始迭代一个向量。不确定我应该怎么做。
我有一个向量 A 和 B。我的矢量 A 有 10 个元素 PC1-PC10 我的矢量 B 有 20 个元素 用户1-用户20.
所以我想做的是当我的向量 A 和 B 都到达第 10 个元素时,意思是说向量 [= 的最后一个元素21=]A,我想重复迭代向量 A 但从第 11 开始迭代向量 B 元素,以便我可以用它做一些事情。
下面是我想出的简化代码,但从技术上讲它是一样的:
vector<string>::iterator b = vecB.begin();
for (int i = 1; i < 2; i++) {
for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; a++) {
if (a == vecA.end()) {
b = vecB.begin() + 10; //here the iterator for verB should start from the 11th element
}
++b
}
}
我应该弄乱向量 B 的迭代器吗?或者有其他选择吗?
编辑
看来我终究是问错了问题。我已经标记了这个问题的答案,很快就会发布另一个。感谢您对我的问题的快速回复!
您无需更改 B 的迭代器,它会自动从第 11 个元素继续。但是您需要在 for 循环开始时在 A 上重新开始迭代(或者您将使用 a.end()
这不是有效元素):
if (a == vecA.end()) {
a = vecA.begin();
}
您还应该遍历两者,但只检查 b
上的结束;如果您检查 a
,for
将在 if
变为真之前结束:
for (auto a = vecA.begin(), b = vecB.begin(); b != vecB.end(); ++a, ++b)
你可以看到完整的代码here。
嵌套循环内的if
条件永远不会为真,因为它与循环条件冲突:
for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; a++) {
// This check ----------------------------------^^^^^^^^^^^^^^^
// guarantees that this will never succeed:
// vvvvvvvvvvvvvvv
if (a == vecA.end()) {
...
}
}
你应该像这样重写代码:
vector<string>::iterator b = vecB.begin();
// Check that vecB has sufficient number of elements before entering the loop.
for (int i = 1 ; i < 2 ; i++) {
for (vector<string>::iterator a = vecA.begin(); a != vecA.end() ; ++a, ++b) {
...
}
// At this point we know for sure that a == vecA.end(),
// because it is a post-condition of the for loop above.
b = std::next(vecB.begin(), 11);
}
++b
的调用可以移到循环头中。
注意std::next
的用法:虽然
b = vecB.begin() + 10;
针对向量进行编译,不保证对所有类型的容器都适用。使用 std::next
代替:
b = std::next(vecB.begin(), 11);
注意: 此代码假设 vecB
至少比 vecA
多 11 个元素。如果您在进入循环之前检查该假设,这可能没问题。如果这个假设被打破,代码将有未定义的行为。
除了使用std::next
,如@dasblinkenlight的回答所示,还可以使用std::advance
.
b = vecB.begin();
std::advance(b, 10);
我实际上更喜欢手动迭代 C++11 之前的向量,因为它看起来比 iterators
:
for (unsigned int i = 0; i < my_vector.size(); i++) {
my_vector[i]; //Do Something
}
您可以简单地通过修改 for 循环条件(即 unsigned int i = n
)来指定要迭代的范围
编辑:在投票之前实际上阅读了我的整个答案。在向量上使用迭代器过于冗长并且使您的代码几乎不可读。如果有正当理由不应使用此方法来支持迭代器,请发表评论。
大多数人并不是在寻找超通用的、可放入任何容器的解决方案。大多数人都知道他们需要一个动态列表,vector
符合要求,那么为什么不让您的代码易于下一个人阅读呢?
其他人已经回答了如何重置或推进迭代器,所以我只回答,如何以更简单的方式解决您的问题。使用索引而不是两个迭代器并行迭代两个向量要简单得多:
// assumes vecB is bigger than vecA as described in the question
for (std::size_t i = 0; i < vecB.size(); i++) {
auto user = vecB[i];
auto pc = vecA[i % vecA.size()];
}
注意较小的向量是如何使用余数运算符迭代的。