簡體   English   中英

在 C++ 中迭代多個 std::vectors 的簡單方法

[英]Easy way to iterate through multiple std::vectors in C++

我有兩個相同類型的std::vector ,我需要使用相同的例程遍歷它們。 像這樣:

std::vector<int> values1, values2;
int counter = 0;
for (int val : values1) counter += val;
for (int val : values2) counter += val;

有什么簡單的方法可以在一個循環中編寫最后兩行,以避免代碼重復? 看起來像這樣的東西:

std::vector<int> values1, values2;
int counter = 0;
for (int val : values1, values2) counter += val;

如果在迭代它們之后不需要訪問任何一個向量,則可以將它們移動到std::initializer_list中,然后對其進行迭代:

std::vector<int> values1{1, 2, 3};
std::vector<int> values2{4, 5, 6};

for (const auto& v : {std::move(values1), std::move(values2)}) {
    for (auto value : v) {
        std::cout << value << ' ';
    }
}

// prints "1 2 3 4 5 6 "

正如 ShadowRanger 在下面指出的那樣,如果我們迭代std::reference_wrapper的初始化列表,則不需要從原始向量移動。 這可以通過將std::movestd::cref交換(或std::ref如果你需要改變它們)來完成:

for (const auto& v : {std::cref(values1), std::cref(values2)}) {
    for (auto value : v.get()) {
        std::cout << value << ' ';
    }
}
// prints "1 2 3 4 5 6 ", as before

不,沒有,抱歉。 至少不是直接用語言。

Boost 可以做到

for (int val : boost::range::join(values1, values2))
   counter += val;

因為 Boost 可以做到這一點,所以您也可以通過制作自己的迭代器類型來對 collections 投射“視圖”。

但是,特別是在您展示的簡單案例中,通常不值得。 如果您的循環體更復雜,我建議將其拆分為采用int的 function。 這可以只是在循環上方聲明的 lambda。 我就是做這個的。

使用 range-v3 你可以這樣寫:

namespace rs = ranges;
namespace rv = ranges::views;

int counter = rs::accumulate(rv::concat(values1, values2), 0);

我懷疑 C++23(或 C++2b)將對此提供庫支持。 所需要的只是一個范圍適配器views::concat<numeric> header 的范圍化。

怎么樣:

std::vector<int> values_vecs[2];
// ... 
int counter = 0;
for (const auto& values : values_vecs)
    for (int val : values) counter += val;

它與您的原始代碼不完全相同,但它可以輕松支持 2 個以上的向量。

如果向量已經作為兩個單獨的向量存在,您仍然可以使用 go:

std::vector<int> values1, values2;
//... 
int counter = 0;
for (auto values_ptr : {&values1, &values2})
    for (int val : *values_ptr) counter += val;

我使用類似這樣的方法遍歷 3 個不同大小的向量,其中一個向量依賴於其他兩個向量(first_vector 依賴於其他向量)。

#include <iostream>
#include <vector>
int main() {
  std::vector<int> first_vector{50, 20, 30, 5000};
  std::vector<int> second_vector{10};
  std::vector<int> third_vector{500, 10};
  for (int i = 0, j = 0, k = 0; i < first_vector.size(); ++i, ++j, ++k) {
    if (j == second_vector.size()) {
      j = 0;
    }
    if (k == third_vector.size()) {
      k = 0;
    }
    std::cout << first_vector[i] << '|' << second_vector[j] << '|'
              << third_vector[k] << '\n';
    std::cin.get();
  }
  return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM