在 C++ 中从单个向量创建对向量

Sch*_*tky 25 c++ stl std stdvector std-pair

我有一个偶数大小的向量,我想将其转换为成对的向量,其中每对始终包含两个元素。我知道我可以使用简单的循环来做到这一点,但我想知道是否有一个很好的标准库工具可以做到这一点?可以假设原始向量始终包含偶数个元素。

例子:

vector<int> origin {1, 2, 3, 4, 5, 6, 7, 8};

vector<pair<int, int>> goal { {1, 2}, {3, 4}, {5, 6}, {7, 8} };
Run Code Online (Sandbox Code Playgroud)

Enr*_*lis 21

使用范围-v3:

#include <range/v3/range/conversion.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/chunk.hpp>

using namespace ranges;
using namespace ranges::views;

int main() {
    std::vector<int> origin {1, 2, 3, 4, 5, 6, 7, 8};
    std::vector<std::pair<int, int>> goal {{1, 2}, {3, 4}, {5, 6}, {7, 8}};

    auto constexpr makePairFromRangeOf2 = [](auto two){
        return std::make_pair(two.front(), two.back());
    };

    auto result = origin | chunk(2)
                         | transform(makePairFromRangeOf2)
                         | to_vector;
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您只需循环 on result,那么您只需要它是一个范围,因此您可以省略| to_vector,因为您仍然可以执行result.begin()and result.end(),这就是result范围的组成部分。

如果您不需要内部容器真正成为std::pairs,但您只是对调用感到满意,比如说,result.front().front()而不是result.front().first,那么您也可以离开transform,并且对 感到满意auto result = origin | chunk(2);

您没有提到为什么您只想要一个标准解决方案。但是请考虑这<ranges> C++20 中的标准。不幸的是,该功能不如 C++20 Range-v3 之前的库强大。但我认为毫无疑问,它会在某个时刻(C++23?)。

  • 事实上,[C++23 已经采用了 `ranges::to` 和 `views::chuck`](https://en.cppreference.com/w/cpp/compiler_support),所以这*实际上*是“标准”的答案。 (7认同)
  • https://godbolt.org/z/GsqWG1WW7 (4认同)

ein*_*ica 13

正如 @\xe5\xba\xb7\xe6\xa1\x93\xe7\x91\x8b 提到的,如果您还愿意使用ranges-v3库,您可以使用视图chunk()

\n
std::vector origin = {1, 2, 3, 4, 5, 6, 7, 8};\nauto goal = origin | ranges::views::chunk(2) | ranges::to<std::vector>;\n
Run Code Online (Sandbox Code Playgroud)\n

看到它正在运行GodBolt

\n

与我的其他答案不同,这在语言方面是完全有效的。

\n

注意事项:

\n
    \n
  • 这将复制您的数据!
  • \n
  • 可能会在你的目标代码中引入一堆东西(错误字符串、异常处理程序等)。
  • \n
  • 范围库显着增加了编译时间(尽管启用 C++20 后编译时间可能会减少?)
  • \n
  • 不基于标准库 - 但显然chunk()to()在 C++23 中,因此只要稍作语法调整(例如添加std::),这将是仅包含标准库的有效 C++23。
  • \n
  • 的元素goal不是std::pairs,而是范围。您将需要获取第一个和第二个元素,或者第一个和最后一个元素来形成实际的对。
  • \n
\n


Dar*_*deX 6

我有一个处理向量中偶数和奇数元素的函数。它的作用是需要另一个参数在对的末尾添加一个数字。我认为截至目前还没有任何标准工具/库可以这样做C++ 20,有一个Range-v3C++ 23尚未发布。

这是在线尝试链接。

#include <iostream>
#include <vector>

// time complexity: O(n / 2), where `n` is the length of `my_vec`
std::vector<std::pair<int, int>> vec_to_pair(const std::vector<int> &my_vec, int odd_origin)
{
    std::vector<std::pair<int, int>> val;
    for (std::size_t i = 0; i < my_vec.size(); i += 2)
    {
        int sec_val;
        if (i < my_vec.size() - 1)
            sec_val = my_vec[i + 1];
        else if (my_vec.size() % 2 != 0)
            sec_val = odd_origin;
        else 
            break;
        int data[] = {my_vec[i], sec_val};
        val.push_back({data[0], data[1]});
    }
    return val;
}

void print(const std::vector<std::pair<int, int>> &vec)
{
    std::cout << "{ ";
    for (auto &&i : vec)
        std::cout << "{ " << i.first << ", " << i.second << " }  ";
    std::cout << " }" << std::endl;
}

int main(void)
{
    std::vector<int> vec1 = {1, 2, 3, 4, 5};    // odd
    std::vector<int> vec2 = {1, 2, 3, 4, 5, 6}; // even

    auto x1 = vec_to_pair(vec1, -1);
    auto x2 = vec_to_pair(vec2, 0);

    print(x1);
    print(x2);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)