从给定向量的块中生成新向量

Generate a new vector out of blocks of a given vector

我有一个 std::vector,其中存储了大约 100 万个值。现在我想将向量分成 N 个给定大小的块,并通过从原始向量中随机拉出 N 个块来创建一个新的 std::vector。这是我目前所拥有的,这只是为了获得一个想法。

int main {  
    int breakPoint = 2;
    std::vector<int> test = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::vector<int> newTest;
    int length = test.size();
    for (size_t i = 0; i < length; i++) {
        int foo = random(breakPoint,length);
        //std::cout << foo << std::endl;
        std::vector<int> subvector(test.begin() + foo, test.begin() + foo + breakPoint);

        for (size_t i = 0; i < subvector.size(); i++){
            newTest.push_back(subvector[i]);
        }
    }
    return 0;
}

int random(int N, int interval){
    int rnd;

    int foo = 1;
    while (foo !=0) {
        rnd = int(randomNumber(0, (interval+1-N)));
        foo = (rnd%N);
    }
    return rnd;
}

randomNumber(a,b)给出区间[a,b)中的一个随机数。这段代码运行并且对于不太大的向量我会这样使用它。但是因为我有一个很大的原始向量,我将不得不多次重复这个新的向量操作,以获得统计数据,我宁愿不使用它。所以我的问题是,如何使这样的操作非常快?第一个问题显然是我如何 select 在 random() 中设置断点。 谢谢你帮助我,干杯!

如何使用 std::vector::insert 将随机块附加到输出向量:

std::vector<int> input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::vector<int> output;

for (size_t i = 0; i != num_blocks; i++) {
    int block_position = getRandomBlock(num_blocks, block_length);
    auto block_begin = input.cbegin() + block_position;
    auto block_end = block_begin + block_length;
    output.insert(output.end(), block_begin, block_end);
}

正如评论所建议的那样,对于非常大的test,这段代码在复制过程中会陷入困境,解决方案是不复制。 (假设测试包含一百万个元素,这意味着您将进行 400 万次随机访问 只是为了复制 。)

只要 test 保持不变,将迭代器保留在 test 中是一种简单的索引方式。

const auto breakPoint = 2;
const std::vector<int> test = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
vector<vector<int>::const_iterator> newTest(test.size());

for(auto& i : newTest){
    i = test.begin() + random(breakPoint, test.size());
}

将迭代器保存在向量中允许我们对它们进行排序,在访问内存之前。所以我们可以利用缓存的空间局部性。

sort(newTest.begin(), newTest.end());

现在要使用 newTest,您只需执行以下操作即可:

for(auto& i : newTest){
    for_each(i, i + breakPoint, [](int foo){cout << foo << ' ';});
    cout << endl;
}

编辑:

random 在宏伟的计划中似乎并没有浪费太多时间,因为它不进行内存访问,但您可以通过搜索合适的 breakPoint 乘数来改进它,而不是试图随机找到一个 breakPoint 增量:

// This change assumes that you've already done srand(time(nullptr));
int random(int N, int interval){
    return (rand() % (interval / N)) * N;
}

您可以看到如何内联这么简单的东西,这将提供允许 interval / N 只计算一次的进一步好处。所以我们的初始化部分现在可以变成:

const auto breakPoint = 2;
const std::vector<int> test = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const auto partitions = test.size() / breakPoint;
vector<vector<int>::const_iterator> newTest(test.size());

srand(time(nullptr));

for(auto& i : newTest){
    i = test.begin() + breakPoint * (rand() % partitions);
}