将子向量合并/展平为单个向量c++(将2d转换为1d)
Merging/flattening sub-vectors into a single vector c++ (converting 2d to 1d)
我有vector<vector<int> > Y
。我想将y内部的子向量(称为y)合并为一个vector<int>
。但我不想对它们进行排序,也就是说,按照它们出现的顺序合并它们。我该如何有效地做到这一点,也许是通过使用STL算法?std::merge
方法通过排序进行合并,这是我不想要的。
编辑:我想要的是:给定{1,6,5},{5,3-1,77},{0},…}return{1,6,5,3,-1,77,0,…}
这个词是串联或扁平:
std::vector<int> a { 1,2,3 },
b {9,0,-7};
std::vector<int> c(begin(a), end(a));
c.insert(end(c), begin(b), end(b));
或者,更简单:
auto c = a;
c.insert(end(c), begin(b), end(b));
c
现在包含1,2,3,9,0,-7
您可以将其概括为处理嵌套容器案例:
template <template<typename...> class R=std::vector,
typename Top,
typename Sub = typename Top::value_type>
R<typename Sub::value_type> flatten(Top const& all)
{
using std::begin;
using std::end;
R<typename Sub::value_type> accum;
for(auto& sub : all)
accum.insert(end(accum), begin(sub), end(sub));
return accum;
}
如果要将元素从第一个容器移动到最后一个容器(以防元素仅可移动或复制成本高昂),请将std::move
与std::back_inserter
结合使用,或将std::make_move_operator
应用于每个源迭代器。
在Coliru上实时观看
更新:可变串联
最初,我希望你能找到一个可变的解决方案:让我展示一下你如何让它变得更通用,所以你可以说:
auto x = to_vector(std::vector<int> { 1,2,3 }, std::list<int> { 9,8,11 }, std::set<int> { 42 });
事实上,我把它做得很一般,以至于你把异构集合连接到"任意"容器中:
// fun with maps:
auto y = concatenate<std::map<long, std::string> >(
std::map<int, const char*> { { 1, "one" }, { 2, "two" } },
std::map<unsigned, std::string> { { 1, "one" }, { 3, "three" } }
);
您会(正确地)认为to_vector
只是concatenate<std::vector<...>>
的一个方便快捷的工具。这是完整的月份,请在Coliru和ideone上观看:
#include <vector>
#include <utility>
#include <iterator>
namespace detail
{
template <typename R>
void do_concatenation(R& accum) {}
template <typename R, typename First, typename... More>
void do_concatenation(R& accum, First const& first, More const&... more)
{
using std::begin;
using std::end;
std::copy(begin(first), end(first), std::inserter(accum, end(accum)));
do_concatenation(accum, more...);
}
}
template <typename Result, typename... Containers>
Result concatenate(Containers const&... containers)
{
Result accum;
detail::do_concatenation(accum, containers...);
return accum;
}
template <typename First, typename... More>
std::vector<typename First::value_type> to_vector(First const& first, More const&... containers)
{
return concatenate<std::vector<typename First::value_type>>(first, containers...);
}
/// demo
#include <set>
#include <list>
#include <iostream>
#include <map>
#include <string>
int main()
{
auto x = to_vector(std::vector<int> { 1,2,3 }, std::list<int> { 9,8,11 }, std::set<int> { 42 });
for (auto i : x)
std::cout << i << " ";
std::cout << std::endl;
// fun with maps:
auto y = concatenate<std::map<long, std::string> >(
std::map<int, const char*> { { 1, "one" }, { 2, "two" } },
std::map<unsigned, std::string> { { 1, "one" }, { 3, "three" } }
);
for (auto kvp : y)
std::cout << "(" << kvp.first << ", " << kvp.second << ")";
}
输出:
1 2 3 9 8 11 42
(1, one)(2, two)(3, three)
template <typename T>
std::vector<T> flatten(const std::vector<std::vector<T>>& v) {
std::size_t total_size = 0;
for (const auto& sub : v)
total_size += sub.size(); // I wish there was a transform_accumulate
std::vector<T> result;
result.reserve(total_size);
for (const auto& sub : v)
result.insert(result.end(), sub.begin(), sub.end());
return result;
}
与@not sehe的解决方案相比,这有一些性能优势:
- 它计算结果的最终大小并预分配存储。这意味着没有必要重复重新分配
- 它使用范围插入,而不是像其他版本那样使用单个元素插入。这允许容器应用一些优化,特别是如果元素是可复制的(即每个内部容器只有一个memcpy)
不利的一面是,它只适用于vector,而不适用于deque或list。
相关文章:
- 将值指定给向量(2D)的向量中的某个位置
- 在 2D 向量中使用第三个 [ ] 有什么意义?
- 如何在 C++ 中使用它的构造函数初始化 unique_ptrs 的 2D 向量?
- 如何在C++或OpenCV子矩阵中的2D子向量上使用OpenACC?
- 哪个更快:在 1d 向量中按字符串搜索还是在 2d 向量中按向量搜索?
- 分配具有 2D 向量大小的变量的内存
- 根据组件 1、2(和 3)对空间 (2D/3D) 向量进行排序
- 在统一内存 CUDA C/C++ 中分配 2D 向量
- 索引 2D 向量时'Reference to type const..'编译错误
- 查找 2D 向量的位置,该向量是类C++的一个元素
- 如何在 C++ 中的函数中传递 2D 向量的子向量
- 为 2D 向量类创建标量乘法运算符
- 无法使用push_back将整数插入1D/2D向量
- 如何将列附加到现代C 中的2D向量
- 如何声明和初始化一个特定尺寸向量的2D数组
- 如何计算 2D 数组中每行的总和并放置在向量中
- 在不使用递归的情况下求解所有 2D 字符串向量组合?(C++)
- 在类中创建向量(2D 数组)的向量 - Error:C++ 需要所有声明的类型说明符
- 在C++中使用向量的向量(2D 向量)表示邻接列表
- 将向量(2D数组)的向量重置为零