【问题标题】:Generate 2 vectors using ranges-v3使用 range-v3 生成 2 个向量
【发布时间】:2021-01-14 18:40:12
【问题描述】:

我有两个不同类型的向量,比如说 int 和 double。我还有第三个带索引的向量,我想提取与 range-v3 索引对应的两个第一个向量的值。

我现在有这个

std::vector<int> A {0,1,2,3,4,5,6,7,8};
std::vector<double> B{0,1,2,3,4,5,6,7,8};
std::vector<int> indices{0,2,3};

const std::vector<int> A_slice = indices | 
    ranges::views::transform([](const auto i) {return 2*i;}) | 
    ranges::views::transform([&A](const auto i) {return A[i]}) |
    ranges::to_vector;

const std::vector<double> B_slice = indices | 
    ranges::views::transform([](const auto i) {return 2*i;}) | 
    ranges::views::transform([&B](const auto i) {return B[i]}) | 
    ranges::to_vector;

这不是最有效的方法,因为您需要迭代两次并进行两次2*i 转换。 一种解决方案是获取一对向量

const auto AB_slice = indices | 
    ranges::views::transform([](const auto i) {return 2*i;}) | 
    ranges::views::transform([&A, &B](const auto i) {return std::make_pair(A[i], B[i]);}) |
    ranges::to_vector;

但这不同于两个独立的向量。 有没有办法获得两个独立的向量?

【问题讨论】:

  • 我不知道 ranges 的事情,但您是否考虑过存储第一次转换的结果并将其用于 A 和 B?
  • 范围是惰性的。它们仅在您迭代时进行评估,在这种情况下,在 to_vector 期间。这样做的好处是您不需要存储它。但显然,它的缺点是你必须迭代两次......
  • 正常循环会更短、更清晰、运行和编译更快:-)
  • 当然,对于这种特殊情况。但这是一个演示示例,询问范围是否可以做一些特别的事情。
  • @jjcasmar,总而言之,您正在寻找unzip 函数。

标签: c++ range-v3


【解决方案1】:

如果你想的话,自己积累它们:

#include <algorithm>
#include <vector>
#include <numeric>
#include <utility>
#include <iostream>
#include <range/v3/all.hpp>
int main() {
    std::vector<int> A {0,1,2,3,4,5,6,7,8};
    std::vector<double> B{0,1,2,3,4,5,6,7,8};
    std::vector<int> indices{0,2,3};

    const auto AB_slice = ranges::accumulate(
        indices | ranges::views::transform([](const auto i) {return 2*i;}),
        std::pair<std::vector<int>, std::vector<double>>(),
        [&](std::pair<std::vector<int>, std::vector<double>> v, int i) { 
            v.first.push_back(A[i]);
            v.second.push_back(B[i]);
            return std::move(v);
        }
    );

    for (auto i : AB_slice.first) {
        std::cout << i << "\n";
    }
    for (auto i : AB_slice.second) {
        std::cout << i << "\n";
    }
}

【讨论】:

  • 这很有趣。我从来没有这样想过范围!
  • std::move 不是多余的,考虑到v 是一个副本?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 1970-01-01
  • 1970-01-01
  • 2020-07-26
  • 2015-07-11
  • 2019-12-16
  • 2023-03-19
相关资源
最近更新 更多