是否有一个 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::vector
s 构造函数:
#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<=i<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);
【讨论】:
非常感谢 或者,您可以使用这些迭代器表示的范围(无需复制所有数据)。而且您证明了<algorithm>
的设计决定是采用迭代器对而不是容器作为参数
@Caleth 我的一般建议是“不要这样做”。通常它会让人觉得很讨厌,但是是的,它可能适合这里。将添加注释【参考方案2】:
对此没有标准功能。函数会返回什么?更多向量的向量?这对于在家解决问题来说很好,但我觉得标准委员会不会对这样做的功能感到满意。或者如果要将迭代器带到目标向量,有多少个目标向量?这些东西会被定义。而且我不认为委员会会乐于为每个输出向量的数量制定 N 个新算法。
但是,您可以滚动自己的函数,广泛使用部分向量复制:
std::vector<int> newVec(oldVec.begin(), oldVec.begin() + 8);
// copies the first 8 elements of oldVec into newVec
【讨论】:
我认为这正是我想要的。非常感谢!以上是关于是否有一个 C++ 函数可以将向量分成三个单独的向量?的主要内容,如果未能解决你的问题,请参考以下文章
是否有一个函数可以从向量中删除一个元素而不在 c++ stdlib 中移动它?