博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
连接两个std :: vector
阅读量:3577 次
发布时间:2019-05-20

本文共 10063 字,大约阅读时间需要 33 分钟。

如何连接两个<ode>std::vector ?


#1楼

我会使用 ,类似:

vector
a, b;//fill with datab.insert(b.end(), a.begin(), a.end());

#2楼

vector1.insert( vector1.end(), vector2.begin(), vector2.end() );

#3楼

std::vector
first;std::vector
second;first.insert(first.end(), second.begin(), second.end());

#4楼

或者您可以使用:

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

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


#5楼

如果您使用的是C ++ 11,并且希望移动元素而不是仅复制它们,则可以将与insert(或copy)一起使用:

#include 
#include
#include
int main(int argc, char** argv) { std::vector
dest{1,2,3,4,5}; std::vector
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
(std::cout, "\n") ); return 0;}

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

#include 
#include
#include
int main(int argc, char** argv) { std::vector
> dest{
{1,2,3,4,5}, {3,4}}; std::vector
> 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的新元素。


#6楼

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

template
inline void append_copy(std::vector
& v1, const std::vector
& 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; }}

如果向量元素的move构造函数可以抛出(不太可能,但仍然可以),则通常无法实现具有强烈保证的类似append_move


#7楼

对于C ++ 11,我更喜欢以下将向量b附加到a:

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

ab不重叠时,并且b将不再使用。


这是从<algorithm> ,不是通常<utility>


#8楼

将此添加到您的头文件:

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

并以这种方式使用它:

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

r将包含[1,2,62]


#9楼

如果您要查找的是在创建后将向量附加到另一个向量的方法,那么是您最好的选择,例如多次回答,例如:

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

遗憾的是,无法构造const vector<int> ,如上所述,您必须先构造然后insert


如果您实际上正在寻找的是容纳这两个vector<int>的串联的容器,那么在以下情况下,可能会有更好的选择:

  1. 您的vector包含基元
  2. 您所包含的原语大小为32位或更小
  3. 你想要一个const容器

如果上述全部正确,则建议使用char_typevector包含的基元大小匹配的 。 您应该在代码中包含 ,以验证这些大小保持一致:

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

有了这个信念,您就可以做到:

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

有关stringvector之间差异的更多信息,请参见此处: :

有关此代码的实时示例,请参见此处: :


#10楼

我更喜欢已经提到的一种:

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

但是,如果您使用C ++ 11,则还有另一种通用方法:

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

同样,这也不是问题的一部分,但是建议在追加之前使用以提高性能。 而且,如果您将vector与自身连接在一起,而没有保留它将会失败,那么您始终应该reserve


所以基本上您需要什么:

template 
void Append(std::vector
& a, const std::vector
& b){ a.reserve(a.size() + b.size()); a.insert(a.end(), b.begin(), b.end());}

#11楼

vector
v1 = {1, 2, 3, 4, 5};vector
v2 = {11, 12, 13, 14, 15};copy(v2.begin(), v2.end(), back_inserter(v1));

#12楼

老实说,您可以通过将两个向量中的元素复制到另一个向量中来快速连接两个向量,或者仅追加两个向量之一! 这取决于您的目标。

方法1:分配新向量,其大小是两个原始向量大小的总和。

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

方法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());

#13楼

对于 ,您可能会有一个懒惰的串联:

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


#14楼

您应该使用

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

#15楼

这是使用C ++ 11 move语义的通用解决方案:

template 
std::vector
concat(const std::vector
& lhs, const std::vector
& rhs){ if (lhs.empty()) return rhs; if (rhs.empty()) return lhs; std::vector
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
std::vector
concat(std::vector
&& lhs, const std::vector
& rhs){ lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend()); return std::move(lhs);}template
std::vector
concat(const std::vector
& lhs, std::vector
&& rhs){ rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend()); return std::move(rhs);}template
std::vector
concat(std::vector
&& lhs, std::vector
&& 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);}

请注意,这与到vector有何不同。


#16楼

连接的一般性能提升是检查向量的大小。 并合并/插入较小的一个与较大的一个。

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

#17楼

您可以为+运算符准备自己的模板:

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

接下来-使用+:

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

此示例提供输出:

 
1 2 3 4 5 6 7 8

#18楼

这个解决方案可能有点复杂,但是boost-range还提供了其他一些不错的东西。

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

通常,人们的意图是将向量ab组合在一起,然后对其进行迭代以执行某些操作。 在这种情况下,存在可笑的简单join功能。

#include 
#include
#include
#include
int main(int, char**) { std::vector
a = { 1,2,3 }; std::vector
b = { 4,5,6 }; std::vector
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
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)


#19楼

如果希望能够简洁地连接向量,则可以重载+=运算符。

template 
std::vector
& operator +=(std::vector
& vector1, const std::vector
& vector2) { vector1.insert(vector1.end(), vector2.begin(), vector2.end()); return vector1;}

然后您可以这样称呼它:

vector1 += vector2;

#20楼

我已经实现了此功能,该功能可以连接任意数量的容器,从右值引用移至其他位置进行复制

namespace internal {// Implementation detail of Concatenate, appends to a pre-reserved vector, copying or moving if// appropriatetemplate
void AppendNoReserve(Target* target, Head&& head, Tail&&... tail) { // Currently, require each homogenous inputs. If there is demand, we could probably implement a // version that outputs a vector whose value_type is the common_type of all the containers // passed to it, and call it ConvertingConcatenate. static_assert( std::is_same_v< typename std::decay_t
::value_type, typename std::decay_t::value_type>, "Concatenate requires each container passed to it to have the same value_type"); if constexpr (std::is_lvalue_reference_v) { std::copy(head.begin(), head.end(), std::back_inserter(*target)); } else { std::move(head.begin(), head.end(), std::back_inserter(*target)); } if constexpr (sizeof...(Tail) > 0) { AppendNoReserve(target, std::forward
(tail)...); }}template
size_t TotalSize(const Head& head, const Tail&... tail) { if constexpr (sizeof...(Tail) > 0) { return head.size() + TotalSize(tail...); } else { return head.size(); }}} // namespace internal/// Concatenate the provided containers into a single vector. Moves from rvalue references, copies/// otherwise.template
auto Concatenate(Head&& head, Tail&&... tail) { size_t totalSize = internal::TotalSize(head, tail...); std::vector
::value_type> result; result.reserve(totalSize); internal::AppendNoReserve(&result, std::forward(head), std::forward
(tail)...); return result;}

#21楼

C ++ 17有一个算法 ,非常易于使用,

下面是示例:

#include 
#include
#include
int main(){ //DATA std::vector
v1{2,4,6,8}; std::vector
v2{12,14,16,18}; //MERGE std::vector
dst; std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst)); //PRINT for(auto item:dst) std::cout<
<<" "; return 0;}

#22楼

如果您的目标只是为了只读而遍历整个值范围,则另一种方法是将两个向量都包装在代理(O(1))周围,而不是复制它们(O(n)),因此它们在外部视为单个连续的。

std::vector
A{ 1, 2, 3, 4, 5};std::vector
B{ 10, 20, 30 };VecProxy
AB(A, B); // ----> O(1)for (size_t i = 0; i < AB.size(); i++) std::cout << AB[i] << " "; // ----> 1 2 3 4 5 10 20 30std::cout << AB[6]; // ----> 20

有关更多详细信息,请参见 ,包括“ VecProxy”实施以及优缺点。

转载地址:http://urogj.baihongyu.com/

你可能感兴趣的文章
数据结构之列表
查看>>
es5中的arguments对象
查看>>
git本地仓库和远程仓库关联,分支重命名
查看>>
js对象的深拷贝,你真的觉得很简单吗?
查看>>
你真的了解map方法吗?手动实现数组map方法。
查看>>
带你手动实现call方法,让你收获满满
查看>>
前端知识体系
查看>>
使用join查询方式找出没有分类的电影id以及名称
查看>>
Qt教程(2) : Qt元对象系统
查看>>
驱动开发误用指针错误:Unable to handle kernel NULL pointer dereference at virtual address
查看>>
Linux部署DocSystem知识/文件管理系统
查看>>
Centos7开机自启动脚本无法使用备用方案
查看>>
jvm虚拟机内存详解
查看>>
线程的创建方式
查看>>
DNS是什么
查看>>
Hbase架构
查看>>
PaddleX的C++使用
查看>>
MyBatis-Plus代码生成器
查看>>
我的第一个SpringBoot项目(一)
查看>>
回文数
查看>>