将一个向量拆分为几乎相等的子向量,然后存储到另一个向量中

Posted

技术标签:

【中文标题】将一个向量拆分为几乎相等的子向量,然后存储到另一个向量中【英文标题】:splitting one vector into almost-equal sub vectors then storing into another vector 【发布时间】:2020-08-08 20:37:24 【问题描述】:

我正在尝试将一个大型用户给定向量拆分为 x 个子向量。一切“似乎”都按原样工作,但结果不对。

std::vector<std::vector<std::string>> split_to_sub_vectors(std::vector<std::string> initial_vector, int thread_amount) 

    std::cout << "initial size: " << initial_vector.size() << std::endl;

    int size_for_splitting = initial_vector.size();


    std::cout << "split amount: " << thread_amount << std::endl;

    int r = size_for_splitting / thread_amount;
    std::cout << r << " need to be in each sub-vector" << std::endl;

    std::cout << "There will be: " << size_for_splitting % thread_amount << " element remaining" << std::endl;

    std::vector<std::vector<std::string>> perm_vector;



    for (int x = 0; x < thread_amount; x++) 

        std::vector<std::string> temp_vector;

        for (int a = 0; a < r; a++) 
            
            hm++;
            std::cout << hm << std::endl;
            temp_vector.push_back(initial_vector[hm]);
        

        perm_vector.push_back(temp_vector);



    
 
    std::cout << "Size of vector holding the sub vectors after splitting: " << perm_vector.size() << std::endl;
   
    std::cout << perm_vector[0][0];
    return perm_vector;

运行此代码将为您提供:

initial size: 7
split amount: 3
2 need to be in each sub-vector
There will be: 1 element remaining
1
2
3
4
5
6
Size of vector holding the sub vectors after splitting: 3
2

我传入的向量叫做test保存字符串,是这样的:

    test.push_back("1");
    test.push_back("2");
    test.push_back("3");
    test.push_back("4");
    test.push_back("5");
    test.push_back("6");
    test.push_back("7");

直到最后一个 print 语句之前的一切似乎都有效。所以 perm_vector 应该包含 3 个子向量,其中包含主用户给定向量中的每个元素。当您打印 perm_vector[0][0] 时,您会期望输出为“1”,但它是 2,而且 7 也不应该在向量中,6 应该是最后一个,但由于它从 2 开始,所以 7 是在里面。计数器是在函数之外定义的,它从 0 开始。我的问题是为什么它从 2 开始?

【问题讨论】:

hm 在哪里声明和初始化?它不在您发布的代码中。 全局范围定义如下:int hm = 0; 第 172 行的 gremlins 偷走了第一个元素。用minimal reproducible example 证明我错了。 重新考虑使用全局。每次调用split_to_sub_vectors 时,都必须将值重置为零。局部变量听起来更友好。 【参考方案1】:

我在您的代码中发现了两个问题:

    hm 在使用前递增。此外,将其设为全球性毫无意义。 size_for_splitting 是整数除法的结果,所以没有余数

我修改了您的代码,以便解决hm 的问题。我得到了预期的输出&lt;&lt;1, 2&gt;, &lt;3, 4&gt;, &lt;5, 6&gt;&gt;,如上所述缺少7

#include <iostream>
#include<vector>
#include<string>

std::vector<std::vector<std::string> > split_to_sub_vectors(std::vector<std::string> initial_vector, int thread_amount) 
    std::cout << "initial size: " << initial_vector.size() << std::endl;
    int size_for_splitting = initial_vector.size();
    std::cout << "split amount: " << thread_amount << std::endl;

    int r = size_for_splitting / thread_amount;
    std::cout << r << " need to be in each sub-vector" << std::endl;
    std::cout << "There will be: " << size_for_splitting % thread_amount << " element remaining" << std::endl;

    std::vector<std::vector<std::string> > perm_vector;

    int hm = 0;
    for (int x = 0; x < thread_amount; x++) 
        std::vector<std::string> temp_vector;
        for (int a = 0; a < r; a++) 
            std::cout << hm << std::endl;
            temp_vector.push_back(initial_vector[hm]);
            hm++;
        
        perm_vector.push_back(temp_vector);
    

    std::cout << "Size of vector holding the sub vectors after splitting: " << perm_vector.size() << std::endl;
    return perm_vector;


int main()

    std::vector<std::string> test;
    test.push_back("1");
    test.push_back("2");
    test.push_back("3");
    test.push_back("4");
    test.push_back("5");
    test.push_back("6");
    test.push_back("7");
    std::vector<std::vector<std::string> > out = split_to_sub_vectors(test, 3);

【讨论】:

很好的答案,但我们通常会尽量避免为学生做作业。 :) 只是需要练习一下 :) :) 去过那里,做过很多次。欢迎来到 SO! 我不是学生,但我是 C++ 新手 :),太年轻了,不能成为学生。我正在从 python 切换到 c++,我可以使用 numpy 来做到这一点。【参考方案2】:

即使 hm 从 0 开始,您在使用它之前也会增加它。可能如果您在内部 for 循环结束时递增,您可能会得到您期望的输出。很难说这个问题,因为我不知道'initial_vector'中有什么,我假设initial_vector[0] = 1?

【讨论】:

@cli 这是正确的答案。您正在跳过initial_vector 的第一个元素。 那么看来你应该在'temp_vector.push_back(initial_vector[hm]);'之后增加hm,否则你会错过索引0 几乎可以肯定是正确的答案,但没有 MRE 作为证据,我坚持我的小精灵小偷的说法。 我刚刚测试过,这确实是修复【参考方案3】:

如果你使用 range-v3 库,实现这个逻辑会变得更容易,而且更不容易出错:

#include <range/v3/all.hpp>

namespace rs = ranges;
namespace rv = ranges::views;

auto split_to_sub_vectors(std::vector<std::string> initial_vector, int thread_amount) 
    
    auto res = initial_vector 
             | rv::chunk(thread_amount) 
             | rs::to<std::vector<std::vector<std::string>>>;
     
    if (res.back().size() != thread_amount)
         res.pop_back();
  
    return res;

这是demo。

【讨论】:

以上是关于将一个向量拆分为几乎相等的子向量,然后存储到另一个向量中的主要内容,如果未能解决你的问题,请参考以下文章

将二进制字符串拆分为长度为 n 的子字符串,然后解码 R 中的每个子字符串

将类成员向量的内容复制到另一个向量中,然后将它们交换回来

C ++ - 将文本文件作为字符串读取,然后将字符串拆分为向量

将 3D MatND 拆分为 2D Mat opencv 的向量

如何将向量拆分为列 - 使用 PySpark

将向量拆分为向量的向量