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

时间:2015-02-19 11:48:52

标签: c++ random 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]中给出一个随机数。这个代码运行,并且对于不太大的向量,我会以这种方式使用它。但由于我有一个大的orignial向量,我将不得不多次重复这个新的向量操作,为了获得统计数据,我宁愿不使用它。所以我的问题是,如何快速完成这样的操作?第一个问题显然是我如何在random()中选择一个断点。 谢谢你的帮助,欢呼!

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

正如评论为非常大的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);
}