有没有一种简单的方法来连接多个向量?

5

目前有一种方法可以使用一个函数将两个向量连接或合并。

但是,似乎没有办法使用一个函数将三个以上的向量连接或合并。

例如,

vector<string> a = {"a", "b"};
vector<string> b = {"c", "d"};
vector<string> c = {"e", "f"};
vector<string> d = {"g", "h"};

// newVector has to include {"a", "b", "c", "d", "e", "f", "g", "h"}
vector<string> newVector = function(a, b, c, d);

如果没有,似乎可以使用可变模板来实现。但是,我无法想象如何通过可变模板来实现。是否有其他解决方案?

1
我不太确定关于变长模板的内容,可以考虑使用for (auto v : { a, b, c, d }) { newVector.insert(newVector.end(), v.begin(), v.end()); }吗?这只有3行代码,而且很清楚地说明了正在发生的事情。 - Tas
@Tas 谢谢,这是一个有趣的解决方案。但是我能否将其功能化,假设向量类型可以是任何东西,例如int,double(合并相同类型的向量)? - sungjun cho
@sungjuncho 关于{a, b, c, d}需要注意的一点是它会复制ab等。你可以使用{&a, &b, &c, &d}来避免这个问题。请参考我的答案,其中包含一个函数化的示例。 - Remy Lebeau
3个回答

5
如果您可以使用range v3,您可以简单地执行以下操作:
std::vector<std::string> allVec = ranges::view::concat(a, b, c, d);

请查看此处的演示

您可以将其与任何矢量类型一起使用。


3

这里提供了一个使用 可变参数模板 的解决方案。

template<typename T, typename ...Args>
void appendVector(vector<T>& v1, vector<T>& v2, Args... args)
{
     v1.insert(v1.end(), v2.begin(), v2.end());
     appendVector(v1, args...);
}

template<typename T>
void appendVector(vector<T>& v1, vector<T>& v2)
{
    v1.insert(v1.end(), v2.begin(), v2.end());
}

您只需要将您的向量附加在一起:

vector<string> newVector;
newVector.reserve(a.size()+b.size()+c.size()+d.size());
appendVector(newVector, a, b, c, d);

作为一种优化,有没有办法在插入输入向量之前使用reserve()预分配目标向量的最终大小?如果目标向量不必在每次插入时重新增加其容量,那就太好了。 - Remy Lebeau
此外,除非我读错了这段代码,否则当添加多个输入向量时,这段代码是否会修改输入向量?这可能不是一个理想的副作用。 - Remy Lebeau
@RemyLebeau 感谢您查看 side effect。现在已经修复了。关于 reserve(),我不太确定它有多高效。 - miradham
2
你甚至可以在函数内部删除递归调用并计算保留大小 C++17演示 - Jarod42

3
尝试这样做: ```` 试试这个方法: ````
template<typename T>
std::vector<T> merge(std::initializer_list<std::vector<T>*> vecs)
{
    size_t size = 0;
    for(auto v : vecs) { size += v->size(); }
    std::vector<T> ret;
    ret.reserve(size);
    for(auto v : vecs) { ret.insert(ret.end(), v->begin(), v->end()); }
    return ret;
}

std::vector<std::string> a = {"a", "b"};
std::vector<std::string> b = {"c", "d"};
std::vector<std::string> c = {"e", "f"};
std::vector<std::string> d = {"g", "h"};

std::vector<std::string> newVector = merge({&a, &b, &c, &d});

实时演示

或者:

template<typename T>
std::vector<T> merge(std::initializer_list<std::reference_wrapper<const std::vector<T>>> vecs)
{
    size_t size = 0;
    for(auto &v : vecs) { size += v.get().size(); }
    std::vector<T> ret;
    ret.reserve(size);
    for(auto &v : vecs) { ret.insert(ret.end(), v.get().begin(), v.get().end()); }
    return ret;
}

std::vector<std::string> a = {"a", "b"};
std::vector<std::string> b = {"c", "d"};
std::vector<std::string> c = {"e", "f"};
std::vector<std::string> d = {"g", "h"};

std::vector<std::string> newVector = merge({std::cref(a), std::cref(b), std::cref(c), std::cref(d)});

实时演示


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接