Pertanyaan Menggabungkan vektor vektor ke dalam satu vektor


Saya memiliki vektor vektor T:

std::vector<std::vector<T>> vector_of_vectors_of_T;

Saya ingin menggabungkan semuanya menjadi satu vektor T:

std::vector<T> vector_of_T;

Saat ini saya menggunakan metode ini:

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

Apakah ada metode yang lebih sederhana? Seperti fungsi std siap? Jika tidak, apakah ada cara yang lebih efisien untuk melakukannya secara manual?


20
2018-02-09 09:00


asal


Jawaban:


Ini latihan yang bagus untuk mencoba dan menulis generik join. Kode di bawah ini mengambil wadah bersarang R1<R2<T> dan mengembalikan wadah yang digabungkan R1<T>. Perhatikan bahwa karena parameter pengalokasi di Pustaka Standar, ini agak tidak praktis. Tidak ada upaya yang dilakukan untuk memeriksa kompatibilitas alokator dll.

Untungnya, ada action::join berfungsi di perpustakaan range-v3 mendatang oleh Eric Niebler, yang sudah cukup kuat dan bekerja hari ini di 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";
}

Contoh Langsung


10
2018-02-09 12:19



Menggunakan back_inserter dan 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));
}

Dari pada copying, std::move memberikan peningkatan kinerja sedikit.


8
2018-02-09 09:11



Saya kira Anda bisa mencoba std::merge/std::move digunakan dalam satu loop - yang sudah ada algoritma std. Tidak tahu apakah itu lebih cepat.


2
2018-02-09 09:10