【问题标题】:Single iterator for 2 vectors holding different elements (c++)用于包含不同元素的 2 个向量的单个迭代器 (c++)
【发布时间】:2021-09-17 22:25:56
【问题描述】:

我有两个长度相同的向量。其中一个拥有 double 向量:

std::vector<std::vector<double>> A;

第二个是双打

std::vector<double> B;

“相同长度”是指 A 包含的 double 向量与 B 包含 double 的向量一样多。 我想同时用一个迭代器遍历它们。我有一种感觉,我需要创建一个类来做到这一点。类似的东西

std::vector<vector<double>>::iterator iter = A.begin();
for (A= iter.begin(); iter != A.end(); iter++)
{
 (*iter).A // I access an element of A std::vector<double>
 (*iter).B // I access an element of B (double)
}

我检查了一个类似的问题,这个问题非常接近我想要做的:C++ iterating over 2 vectors using for loop 但在我的情况下,迭代器有两种不同的类型,分别是std::vector&lt;vector&lt;double&gt;&gt;::iteratorvector&lt;double&gt;::iterator,所以这个问题的解决方案不起作用,但我想它是非常接近的。

我该怎么做?最好的方法是什么?

【问题讨论】:

  • 不只使用下标的原因是什么?此外,您可以使用while 而不是for,在提供的链接中执行相同的操作。
  • "只有一个迭代器" 为什么?我的意思是,您可以创建一个自定义迭代器类,该类包含两个迭代器并将工作委托给它们,但这看起来工作量很大,但收效甚微。为什么不只使用两个迭代器?
  • @n.1.8e9-where's-my-sharem。我不介意使用 2 个迭代器,但是如何使用我的 for 循环来做到这一点?我应该只在 for( iter =A.begin(); iter! = A.end(); iter++) 中使用 iter 并在循环主体中使用 iter2++ 更新 iter2 吗?我对最佳实践感兴趣。
  • afaik 标准库中没有任何东西可以开箱即用,但有例如boost::zip_iterator
  • @rawrex 我没有具体的理由。我对 C++ 相当陌生,但我认为应该出于这种原因使用迭代器而不是使用下标循环(我假设您的意思是在 A[i] 中使用 i 作为下标?)

标签: c++ vector iterator


【解决方案1】:

原则上,您可以编写一个自定义迭代器,它有一个first 和一个second,分别引用AB 的元素。然而,自定义迭代器并不简单。更简单的替代方法是使用普通的基于索引的循环:

for (size_t i = 0; i < A.size() && i < B.size(); ++i)
{
     A[i]; // I access an element of A std::vector<double>
     B[i]; // I access an element of B (double)
}

或者使用两个迭代器

auto itA = A.begin();
auto itB = B.begin();
for ( ; itA != A.end() && itB != B.end(); ++itA,++itB) {
    //...
}

您也可能对 boost 中的 zip_iterator 或 range-v3 库中的 view::zip 感兴趣:

#include <iostream>
#include <vector>
#include <range/v3/view.hpp>    

int main() {
    std::vector<int> A{1,2,3,4,5};
    std::vector<double> B{1.2,3.4,5.6,7.8,9.1};
    for (const auto& [a, b] : ranges::view::zip(A, B)) { 
        std::cout << a << "  " << b << "\n";
    }
}

Live Demo

标准范围库基于 Nieblers 范围,但到目前为止 zip 还没有进入标准库。如果我理解正确的话,这是 C++23 所期望的。


PS:请注意,您的for (A= iter.begin(); iter != A.end(); iter++) 可以被视为“老式”。从 C++11 开始,有 range based for loops,可以让您从头到尾迭代容器的元素。他们进一步向您隐藏迭代器(它们仍然存在)以减少拼写错误的机会。虽然,就像基于迭代器的循环比基于索引的循环更不灵活一样,基于范围的循环也比基于迭代器的循环更不灵活。它们只允许您从 begin 迭代到 end

for (const auto& a : A) { 
    a; // a is a const reference to element in A
}

我只是为了完整起见而提到这一点,与旧的基于迭代器的循环一样,使用基于范围的循环将两个迭代器“压缩”成一个既不简单也不复杂。

【讨论】:

  • 对于 for 的迭代器的外部定义,总是有路要走。
  • @rawrex 不确定是否有一些较新的功能可以在 init 语句中声明两者。然后为了对称,宁愿两个都在外面,而不是一个在循环之外,另一个在循环中
  • 使用 range-v3:for (const auto&amp; [a, b] : ranges::view::zip(A, B)) { /*..*/} :-)
猜你喜欢
  • 2017-12-29
  • 1970-01-01
  • 1970-01-01
  • 2012-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-29
  • 2015-01-23
相关资源
最近更新 更多