2016-02-09 9 views
20

単一のベクターにベクトルのベクトルをマージこの方法:は、私はTのベクトルのベクトルを持っている

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)); 
} 

もっと簡単な方法はありますか?準備ができた標準機能のように?そうでない場合は、手動で行うより効率的な方法がありますか?

+3

私が求めていますので、私はこの質問は私が尋ねる前に、このことについて疑問を持っていた – Default

+0

@Luca Pizzamiglioの感謝のためのより良いフィットすると思います..しかし、それを行うstdの方法。それはここにも当てはまるかもしれません... –

+0

@defaultをcorrecingためhttp://codereview.stackexchange.com/ –

答えて

10

一般joinを試してみてください。以下のコードは入れ子になったコンテナR1<R2<T>を受け取り、結合されたコンテナ​​を返します。標準ライブラリのアロケータパラメータのため、これは少し面倒です。などアロケータの互換性を確認するために行われている試み

は幸いなことに、action::join機能は、エリックNieblerによって、今後の範囲-V3ライブラリにありません、それはすでにかなり堅牢で、クランに今日働く:

#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"; 
} 

Live Example

+3

ところで、このような「結合可能なコンテナ」の数学用語は[monad](https://en.wikipedia.org/wiki/Monad_%28functional_programming%29)です。(概念はイテレータで書くことができるものよりもかなり一般的です。) – leftaroundabout

2

私はループ内で使用されているstd::merge/std::moveを試してみることができます。これはすでに既存の標準アルゴリズムです。それがより速いかどうかわからない。

8

back_inserterおよびmoveを使用する。

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)); 
} 

代わりのcopyingstd::moveはそれをビット性能向上を与えます。

+4

ベンチマークなしで、抽象的な観点からは、私の方が速いのでしょうか?それ以前にも予約が必要ですか? –

+0

@HubertApplebaum私は感謝を参照 –

+0

これは、イテレータを移動する範囲挿入バージョン(特に、範囲の挿入が大幅に最適化される可能性がある)のために特に効率的ではありません。 –

関連する問題