从给定矢量的块中生成一个新矢量

Generate a new vector out of blocks of a given vector

本文关键字:新矢量 一个      更新时间:2023-10-16

我有一个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)。这段代码运行,对于不太大的向量,我会这样使用它。但由于我有一个很大的原始向量,为了获得统计数据,我必须多次重复这个新的向量操作,所以我宁愿不使用它。所以我的问题是,如何使这样的操作非常快?第一个问题显然是如何在random()中选择断点。谢谢你帮我,干杯!

正如评论所建议的,对于一个非常大的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);
}

如何使用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);
}