合并矢量矢量到单个矢量中

Hum*_*awi 20 c++ algorithm vector c++11

我有T矢量矢量:

std::vector<std::vector<T>> vector_of_vectors_of_T;
Run Code Online (Sandbox Code Playgroud)

我想将它们全部合并到T的单个向量中:

std::vector<T> vector_of_T;
Run Code Online (Sandbox Code Playgroud)

我目前正在使用这种方法:

size_t total_size{ 0 };
for (auto const& items: vector_of_vectors_of_T){
    total_size += items.size();
}
vector_of_T.reserve(total_size);
for (auto const& items: vector_of_vectors_of_T){
    vector_of_T.insert(end(vector_of_T), begin(items), end(items));
}
Run Code Online (Sandbox Code Playgroud)

有更直接的方法吗?就像一个准备好的std函数?如果没有,是否有更有效的方法手动完成?

Pra*_*een 10

使用back_insertermove;

size_t total_size{ 0 };
for (auto const& items: vector_of_vectors_of_T){
    total_size += items.size();
}

vector_of_T.reserve(total_size);
for (auto& items: vector_of_vectors_of_T){    
    std::move(items.begin(), items.end(), std::back_inserter(vector_of_T));
}
Run Code Online (Sandbox Code Playgroud)

而不是copying,std::move给它一点性能增强.

  • 没有基准测试,从抽象的角度来看,它应该更快吗?它之前是否需要储存? (4认同)

Tem*_*Rex 10

尝试编写泛型是一个很好的练习join.下面的代码采用嵌套容器R1<R2<T>并返回一个连接容器R1<T>.请注意,由于标准库中的分配器参数,这有点麻烦.没有尝试检查分配器兼容性等.

幸运的是,action::joinEric Niebler即将推出的range-v3库中有这个功能,它已经非常强大,今天在Clang上工作:

#include <range/v3/all.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>

// quick prototype
template<template<class, class...> class R1, template<class, class...> class R2, class T, class... A1, class... A2>
auto join(R1<R2<T, A2...>, A1...> const& outer)
{
    R1<T, A2...> joined;
    joined.reserve(std::accumulate(outer.begin(), outer.end(), std::size_t{}, [](auto size, auto const& inner) {
        return size + inner.size();
    }));
    for (auto const& inner : outer)
        joined.insert(joined.end(), inner.begin(), inner.end());
    return joined;
}

int main()
{
    std::vector<std::vector<int>> v = { { 1, 2 }, { 3, 4 } };

    // quick prototype
    std::vector<int> w = join(v);
    std::copy(w.begin(), w.end(), std::ostream_iterator<int>(std::cout, ",")); std::cout << "\n";

    // Eric Niebler's range-v3
    std::vector<int> u = ranges::action::join(v);
    std::copy(u.begin(), u.end(), std::ostream_iterator<int>(std::cout, ",")); std::cout << "\n";
}
Run Code Online (Sandbox Code Playgroud)

实例

  • 顺便说一句,这种"可连接容器"的数学术语是[monad](https://en.wikipedia.org/wiki/Monad_%28functional_programming%29).(这个概念比用迭代器编写的任何东西都要普遍.) (4认同)