是否有一个 C++ 函数可以将向量分成三个单独的向量?

Posted

技术标签:

【中文标题】是否有一个 C++ 函数可以将向量分成三个单独的向量?【英文标题】:Is there a C++ function which enables to divide vector into three seperate vectors? 【发布时间】:2021-08-31 12:52:52 【问题描述】:

我正在寻找一种解决方案,将向量分成 3 个元素比例为 9:1:1 的独立向量,例如,如果我们在原始向量中有 1100 个元素,那么我希望得到 3 个连续具有 900、100 和 100 的向量元素。有一个函数 std::partition_copy,但是它只将数据复制到 2 个单独的向量中。

【问题讨论】:

没有内置任何东西。您需要创建自己的函数。 有一个构造函数将两个迭代器用于一系列元素。你只需要调用它 3 次。请注意std::partition_copy 复制元素,即目标元素必须已经存在(除非您使用后插入器) @Jakub Fraszczak 只需向 C++ 标准委员会提交一份提案以包含这样的功能。:) 这听起来很像 X-Y 问题。从拆分的数量和大小来看,我猜您正在将机器学习数据拆分为测试、训练、验证?然后只保留原始向量,并将指向它的迭代器传递给使用它的函数。 这里真正的“历史”问题是 std::vectors 除了实际的向量之外的一切。它们是一种容器,但它们缺乏数学向量的基本特征——主要是“加法”——同时提供了一些不需要的向量(删除一个术语,将下一个移到左边)。恕我直言,他们永远不应该被这样命名。 【参考方案1】:

没有标准的算法可以直接做你想做的事。我想有太多的特殊情况需要考虑。例如,当初始向量只有9个元素时,如何按照9:1:1分配元素?每个分区是否应该至少包含 1 个元素?结果应该是 7:1:1 还是 8:1:0?

但是,您可以使用带有两个迭代器的std::vectors 构造函数:

#include <vector>
#include <iostream>
#include <numeric>

int main() 
    
    std::vector<int> v(10);
    std::iota(v.begin(),v.end(),0);

    size_t mid1 = v.size()*0.8;
    size_t mid2 = mid1+v.size()*0.1;

    std::vector<int> v1v.begin(),v.begin()+mid1;
    std::vector<int> v2v.begin()+v1.size(),v.begin()+mid2;
    std::vector<int> v3v.begin()+v1.size()+v2.size(),v.end();

    for (const auto& e : v1) std::cout << e << " ";
    std::cout << "\n";
    for (const auto& e : v2) std::cout << e << " ";
    std::cout << "\n";
    for (const auto& e : v3) std::cout << e << " ";
    std::cout << "\n";

当以绝对数字给出项目数时,不会出现上述问题,您可以编写一个通用算法,用源向量中的 m_i (0&lt;=i&lt;n) 元素填充 n 向量。

最后但并非最不重要的一点是,考虑复制整个向量,只是为了能够访问它的子范围,这不是很惯用的。与其创建包含部分元素的新向量,不如重构处理这些子范围的方法以采用迭代器而不是向量,即

 template <typename Iterator>
 void do_something_with_vector_elements(Iterator begin,Iterator end);

而不是

 void do_something_with_all_vector_elements(const std::vector<int>& v);

【讨论】:

非常感谢 或者,您可以使用这些迭代器表示的范围(无需复制所有数据)。而且您证明了&lt;algorithm&gt; 的设计决定是采用迭代器对而不是容器作为参数 @Caleth 我的一般建议是“不要这样做”。通常它会让人觉得很讨厌,但是是的,它可能适合这里。将添加注释【参考方案2】:

对此没有标准功能。函数会返回什么?更多向量的向量?这对于在家解决问题来说很好,但我觉得标准委员会不会对这样做的功能感到满意。或者如果要将迭代器带到目标向量,有多少个目标向量?这些东西会被定义。而且我不认为委员会会乐于为每个输出向量的数量制定 N 个新算法。

但是,您可以滚动自己的函数,广泛使用部分向量复制:

std::vector<int> newVec(oldVec.begin(), oldVec.begin() + 8);
// copies the first 8 elements of oldVec into newVec

【讨论】:

我认为这正是我想要的。非常感谢!

以上是关于是否有一个 C++ 函数可以将向量分成三个单独的向量?的主要内容,如果未能解决你的问题,请参考以下文章

是否有一个函数可以从向量中删除一个元素而不在 c++ stdlib 中移动它?

使用 Python JAX/Autograd 的向量值函数的雅可比行列式

是否可以让递归函数调用 C++ 中的另一个函数?

是否可以多线程同时执行非 void 函数? (C++)

C++中的指针和向量

在 C++ 中通过引用与按值将向量传递给函数