Concatenating two std::vectors

后端 未结 25 2288
予麋鹿
予麋鹿 2020-11-22 12:00

How do I concatenate two std::vectors?

相关标签:
25条回答
  • 2020-11-22 12:30

    You can do it with pre-implemented STL algorithms using a template for a polymorphic type use.

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    template<typename T>
    
    void concat(std::vector<T>& valuesa, std::vector<T>& valuesb){
    
         for_each(valuesb.begin(), valuesb.end(), [&](int value){ valuesa.push_back(value);});
    }
    
    int main()
    {
        std::vector<int> values_p={1,2,3,4,5};
        std::vector<int> values_s={6,7};
    
       concat(values_p, values_s);
    
        for(auto& it : values_p){
    
            std::cout<<it<<std::endl;
        }
    
        return 0;
    }
    

    You can clear the second vector if you don't want to use it further (clear() method).

    0 讨论(0)
  • If you are interested in strong exception guarantee (when copy constructor can throw an exception):

    template<typename T>
    inline void append_copy(std::vector<T>& v1, const std::vector<T>& v2)
    {
        const auto orig_v1_size = v1.size();
        v1.reserve(orig_v1_size + v2.size());
        try
        {
            v1.insert(v1.end(), v2.begin(), v2.end());
        }
        catch(...)
        {
            v1.erase(v1.begin() + orig_v1_size, v1.end());
            throw;
        }
    }
    

    Similar append_move with strong guarantee can't be implemented in general if vector element's move constructor can throw (which is unlikely but still).

    0 讨论(0)
  • 2020-11-22 12:32

    This solution might be a bit complicated, but boost-range has also some other nice things to offer.

    #include <iostream>
    #include <vector>
    #include <boost/range/algorithm/copy.hpp>
    
    int main(int, char**) {
        std::vector<int> a = { 1,2,3 };
        std::vector<int> b = { 4,5,6 };
        boost::copy(b, std::back_inserter(a));
        for (auto& iter : a) {
            std::cout << iter << " ";
        }
        return EXIT_SUCCESS;
    }
    

    Often ones intention is to combine vector a and b just iterate over it doing some operation. In this case, there is the ridiculous simple join function.

    #include <iostream>
    #include <vector>
    #include <boost/range/join.hpp>
    #include <boost/range/algorithm/copy.hpp>
    
    int main(int, char**) {
        std::vector<int> a = { 1,2,3 };
        std::vector<int> b = { 4,5,6 };
        std::vector<int> c = { 7,8,9 };
        // Just creates an iterator
        for (auto& iter : boost::join(a, boost::join(b, c))) {
            std::cout << iter << " ";
        }
        std::cout << "\n";
        // Can also be used to create a copy
        std::vector<int> d;
        boost::copy(boost::join(a, boost::join(b, c)), std::back_inserter(d));
        for (auto& iter : d) {
            std::cout << iter << " ";
        }
        return EXIT_SUCCESS;
    }
    

    For large vectors this might be an advantage, as there is no copying. It can be also used for copying an generalizes easily to more than one container.

    For some reason there is nothing like boost::join(a,b,c), which could be reasonable.

    0 讨论(0)
  • 2020-11-22 12:34

    A general performance boost for concatenate is to check the size of the vectors. And merge/insert the smaller one with the larger one.

    //vector<int> v1,v2;
    if(v1.size()>v2.size()) {
        v1.insert(v1.end(),v2.begin(),v2.end());
    } else {
        v2.insert(v2.end(),v1.begin(),v1.end());
    }
    
    0 讨论(0)
  • 2020-11-22 12:35

    With C++11, I'd prefer following to append vector b to a:

    std::move(b.begin(), b.end(), std::back_inserter(a));
    

    when a and b are not overlapped, and b is not going to be used anymore.


    This is std::move from <algorithm>, not the usual std::move from <utility>.

    0 讨论(0)
  • 2020-11-22 12:35

    You can prepare your own template for + operator:

    template <typename T> 
    inline T operator+(const T & a, const T & b)
    {
        T res = a;
        res.insert(res.end(), b.begin(), b.end());
        return res;
    }
    

    Next thing - just use +:

    vector<int> a{1, 2, 3, 4};
    vector<int> b{5, 6, 7, 8};
    for (auto x: a + b)
        cout << x << " ";
    cout << endl;
    

    This example gives output:

    1 2 3 4 5 6 7 8
    0 讨论(0)
提交回复
热议问题