首页 文章

连接两个std :: vector

提问于
浏览
519

我如何连接两个 std::vector

18 回答

  • 0

    使用range v3,您可能会有 lazy 连接:

    ranges::view::concat(v1, v2)
    

    Demo .

  • 21

    如果您正在寻找的是一种在创建后将矢量附加到另一个矢量的方法,那么vector::insert是您最好的选择,因为已经多次回答,例如:

    vector<int> first = {13};
    const vector<int> second = {42};
    
    first.insert(first.end(), second.cbegin(), second.cend());
    

    遗憾的是,没有办法构建 const vector<int> ,如上所述,你必须构建然后 insert .


    如果您实际需要的是容纳这两个 vector<int> 串联的容器,那么可能有更好的选择,如果:

    • 您的 vector 包含基元

    • 包含的基元大小为32位或更小

    • 你想要一个 const 容器

    如果以上都是真的,我建议使用basic_stringchar_type 匹配 vector 中包含的基元的大小 . 您应该在代码中包含static_assert以验证这些大小保持一致:

    static_assert(sizeof(char32_t) == sizeof(int));
    

    有了这个保持真实,你可以这样做:

    const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());
    

    有关 stringvector 之间差异的更多信息,请参阅此处:https://stackoverflow.com/a/35558008/2642059

    有关此代码的实例,您可以在此处查看:http://ideone.com/7Iww3I

  • 31

    使用C 11,我更喜欢将以下向量追加到a:

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

    ab 不重叠时, b 将不再使用 .


    这是来自 <algorithm>std::move,而不是通常的std::move .

  • 125

    如果您对强异常保证感兴趣(当复制构造函数可以抛出异常时):

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

    类似 append_move 有强保证可以't be implemented in general if vector element'的移动构造函数可以抛出(这不太可能,但仍然) .

  • 580
    vector<int> v1 = {1, 2, 3, 4, 5};
    vector<int> v2 = {11, 12, 13, 14, 15};
    copy(v2.begin(), v2.end(), back_inserter(v1));
    
  • 7
    std::vector<int> first;
    std::vector<int> second;
    
    first.insert(first.end(), second.begin(), second.end());
    
  • 135

    您可以为运营商准备自己的模板:

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

    接下来 - 只需使用:

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

    这个例子给出了输出:

    1 2 3 4 5 6 7 8
    
  • 3

    这个解决方案可能有点复杂,但是 boost-range 还有一些其他好东西可以提供 .

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

    通常意图是组合vector ab 只是迭代它做一些操作 . 在这种情况下,有一个荒谬的简单 join 功能 .

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

    对于大型载体,这可能是一个优点,因为没有复制 . 它还可以用于将一般化复制到多个容器 .

    出于某种原因,没有像 boost::join(a,b,c) 这样的东西,这可能是合理的 .

  • 3

    这是使用C 11移动语义的通用解决方案:

    template <typename T>
    std::vector<T> concat(const std::vector<T>& lhs, const std::vector<T>& rhs)
    {
        if (lhs.empty()) return rhs;
        if (rhs.empty()) return lhs;
        std::vector<T> result {};
        result.reserve(lhs.size() + rhs.size());
        result.insert(result.cend(), lhs.cbegin(), lhs.cend());
        result.insert(result.cend(), rhs.cbegin(), rhs.cend());
        return result;
    }
    
    template <typename T>
    std::vector<T> concat(std::vector<T>&& lhs, const std::vector<T>& rhs)
    {
        lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
        return std::move(lhs);
    }
    
    template <typename T>
    std::vector<T> concat(const std::vector<T>& lhs, std::vector<T>&& rhs)
    {
        rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
        return std::move(rhs);
    }
    
    template <typename T>
    std::vector<T> concat(std::vector<T>&& lhs, std::vector<T>&& rhs)
    {
        if (lhs.empty()) return std::move(rhs);
        lhs.insert(lhs.cend(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
        return std::move(lhs);
    }
    

    请注意这与appendvector 的区别 .

  • 2

    我更喜欢已经提到过的一个:

    a.insert(a.end(), b.begin(), b.end());
    

    但是如果你使用C 11,还有一种更通用的方法:

    a.insert(std::end(a), std::begin(b), std::end(b));
    

    此外,不是问题的一部分,但建议在添加之前使用reserve以获得更好的性能 . 如果你将矢量与自身连接起来,而不保留它会失败,那么你总是应该 reserve .


    基本上你需要的是:

    template <typename T>
    void Append(std::vector<T>& a, const std::vector<T>& b)
    {
        a.reserve(a.size() + b.size());
        a.insert(a.end(), b.begin(), b.end());
    }
    
  • 1

    连接的 general performance boost 是检查向量的大小 . 并将较小的一个与较大的一个合并/插入 .

    //vector<int> v1,v2;
    if(v1.size()>v2.size()){
        v1.insert(v1.end(),v2.begin(),v2.end());
    }else{
        v1.insert(v2.end(),v1.begin(),v1.end());
    }
    
  • 35

    你应该使用vector::insert

    v1.insert(v1.end(), v2.begin(), v2.end());
    
  • 0

    说实话,你可以通过两个向量的复制元素快速连接两个向量到另一个向量,或者只是附加两个向量中的一个!这取决于你的目标 .

    Method 1: 指定新矢量,其大小是两个原始矢量大小的总和 .

    vector<int> concat_vector = vector<int>();
    concat_vector.setcapacity(vector_A.size() + vector_B.size());
    // Loop for copy elements in two vectors into concat_vector
    

    Method 2: 通过添加/插入向量B的元素来追加向量A.

    // Loop for insert elements of vector_B into vector_A with insert() 
    function: vector_A.insert(vector_A .end(), vector_B.cbegin(), vector_B.cend());
    
  • 9
    vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
    
  • 1

    将此文件添加到头文件中:

    template <typename T> vector<T> concat(vector<T> &a, vector<T> &b) {
        vector<T> ret = vector<T>();
        copy(a.begin(), a.end(), back_inserter(ret));
        copy(b.begin(), b.end(), back_inserter(ret));
        return ret;
    }
    

    并以这种方式使用它:

    vector<int> a = vector<int>();
    vector<int> b = vector<int>();
    
    a.push_back(1);
    a.push_back(2);
    b.push_back(62);
    
    vector<int> r = concat(a, b);
    

    r将包含[1,2,62]

  • 4

    我会使用insert function,类似于:

    vector<int> a, b;
    //fill with data
    b.insert(b.end(), a.begin(), a.end());
    
  • 72

    如果您正在使用C 11,并且希望移动元素而不是仅仅复制它们,则可以使用std :: move_iterator(http://en.cppreference.com/w/cpp/iterator/move_iterator)以及插入(或复制):

    #include <vector>
    #include <iostream>
    #include <iterator>
    
    int main(int argc, char** argv) {
      std::vector<int> dest{1,2,3,4,5};
      std::vector<int> src{6,7,8,9,10};
    
      // Move elements from src to dest.
      // src is left in undefined but safe-to-destruct state.
      dest.insert(
          dest.end(),
          std::make_move_iterator(src.begin()),
          std::make_move_iterator(src.end())
        );
    
      // Print out concatenated vector.
      std::copy(
          dest.begin(),
          dest.end(),
          std::ostream_iterator<int>(std::cout, "\n")
        );
    
      return 0;
    }
    

    对于带有整数的示例,这不会更有效,因为移动它们并不比复制它们更有效,但对于具有优化移动的数据结构,它可以避免复制不必要的状态:

    #include <vector>
    #include <iostream>
    #include <iterator>
    
    int main(int argc, char** argv) {
      std::vector<std::vector<int>> dest{{1,2,3,4,5}, {3,4}};
      std::vector<std::vector<int>> src{{6,7,8,9,10}};
    
      // Move elements from src to dest.
      // src is left in undefined but safe-to-destruct state.
      dest.insert(
          dest.end(),
          std::make_move_iterator(src.begin()),
          std::make_move_iterator(src.end())
        );
    
      return 0;
    }
    

    移动之后,src的元素保留在未定义但安全的构造状态,并且其前面的元素最后直接转移到dest的新元素 .

  • 0

    或者您可以使用:

    std::copy(source.begin(), source.end(), std::back_inserter(destination));
    

    如果两个向量不包含完全相同类型的东西,则此模式很有用,因为您可以使用某些东西而不是std :: back_inserter将一种类型转换为另一种类型 .

相关问题