C++是否存在可将vector按9:1:1比例拆分为三个独立vector的函数?
C++ 按9:1:1比例拆分vector的实现方案
以下提供三种可直接落地的实现方案,可根据实际场景选择:
方案1:手动遍历实现(兼容性最高、逻辑直观)
不需要依赖STL算法,可自定义是否保留原vector的元素顺序,适合所有C++版本:
#include <vector> template <typename T> void split_vector(const std::vector<T>& src, std::vector<T>& out9, std::vector<T>& out1a, std::vector<T>& out1b) { const size_t total = src.size(); // 按9:1:1计算各分组大小,余数默认归入最后一组,可根据需求调整取舍规则 const size_t sz9 = total * 9 / 11; const size_t sz1 = total * 1 / 11; const size_t sz1b = total - sz9 - sz1; // 预分配空间避免扩容开销 out9.reserve(sz9); out1a.reserve(sz1); out1b.reserve(sz1b); // 顺序拷贝元素,需要移动语义的话改为push_back(std::move(src[i])) for (size_t i = 0; i < sz9; ++i) { out9.push_back(src[i]); } for (size_t i = sz9; i < sz9 + sz1; ++i) { out1a.push_back(src[i]); } for (size_t i = sz9 + sz1; i < total; ++i) { out1b.push_back(src[i]); } }
如果不需要保留原vector的内容,可将入参改为右值引用,配合std::move实现零拷贝拆分。
方案2:复用std::partition_copy实现
单次std::partition_copy仅支持拆分为2组,可通过两次调用实现3组拆分,适合不想手动写循环的场景:
#include <vector> #include <algorithm> #include <iterator> template <typename T> void split_vector(const std::vector<T>& src, std::vector<T>& out9, std::vector<T>& out1a, std::vector<T>& out1b) { const size_t total = src.size(); const size_t sz9 = total * 9 / 11; const size_t sz1 = total * 1 / 11; // 第一次拆分:分出9份和剩余2份 std::vector<T> temp; temp.reserve(total - sz9); out9.reserve(sz9); size_t idx = 0; std::partition_copy(src.begin(), src.end(), std::back_inserter(out9), std::back_inserter(temp), [&idx, sz9](const T&) { return idx++ < sz9; } ); // 第二次拆分:把剩余2份拆为两个1份 idx = 0; out1a.reserve(sz1); out1b.reserve(temp.size() - sz1); std::partition_copy(temp.begin(), temp.end(), std::back_inserter(out1a), std::back_inserter(out1b), [&idx, sz1](const T&) { return idx++ < sz1; } ); }
方案3:随机拆分(适用于训练/验证/测试集划分场景)
如果需要打乱原数据顺序再拆分,可先调用std::shuffle打乱数组后再用上述任意方法拆分:
#include <random> #include <algorithm> // 先打乱原数组,T替换为实际的元素类型 std::vector<T> shuffled_src = src; std::shuffle(shuffled_src.begin(), shuffled_src.end(), std::mt19937{std::random_device{}()}); // 再调用上面的split_vector函数拆分shuffled_src即可
注意事项
- 比例调整:如果原vector大小无法被11整除,可根据业务需求调整分组大小的计算规则,比如使用
std::ceil向上取整第一组大小。 - 性能优化:如果存储的是大对象,优先使用移动语义代替拷贝,可大幅降低内存开销。
- C++20优化:使用C++20及以上版本时,可配合
std::ranges::split_view先切分区间再拷贝,代码更简洁。
内容的提问来源于stack exchange,提问作者Jakub Fraszczak
相关产品推荐
相关产品推荐

