在C ++中,假设您有一个boolean
值的向量,并且您希望在与True值对应的索引中随机选择一个索引。
最有效的方法是什么?
示例:
vector<bool> v(4);
v.at(0)=true
v.at(1)=false
v.at(2)=true
v.at(3)=true
您想要在子集{0,2,3}
中选择一个数字。
到目前为止,我尝试了两种方法:
v.at(rnd_sel_index)
为True
。相当快。 任何比方法2更快的建议?
答案 0 :(得分:3)
也许这是一种更有效的方法。
不是存储那些存在的东西,也不存储不存在的东西,或许最好只存储不存在的东西 - 即包含免费索引的矢量。
此向量的顺序可以很容易地随机化一次,然后您可以从back()
中提取项目,直到它empty()
。
如果您想将项目退回到“自由索引池”,只需将它们插入到向量中的随机位置即可。
答案 1 :(得分:1)
您可以使用众所周知的方法从未知长度的序列中选择元素。
示例代码:
#include <random>
#include <iostream>
#include <vector>
#include <algorithm>
std::size_t choose_element(const std::vector<bool>& v) {
auto last = v.end();
auto chosen_i = std::find(v.begin(), last, true);
auto i = std::find(std::next(chosen_i), last, true);
double n = 2.0;
static auto random_generator = std::mt19937{std::random_device{}()};
while (i != last) {
if (std::bernoulli_distribution(1.0 / n)(random_generator))
chosen_i = i;
i = std::find(std::next(i), last, true);
++n;
}
return std::distance(v.begin(), chosen_i);
}
int main() {
std::vector<bool> v = {true, true, false, true};
std::vector<int> indexes(v.size());
const double N = 100;
for (int i=0; i<N; ++i)
++indexes[choose_element(v)];
for (auto& index : indexes)
std::cout << std::distance(indexes.data(), &index) << ": " << (index / N) << "\n";
return 0;
}
这具有可预测的性能,只需要一次通过数据。当然,如果您从同一个向量中获取多个样本,将数据重组为不同的格式然后从中进行绘制可能会更有效。此外,如果几乎所有元素都为真,那么您的方法(2)在一般情况下可能表现更好。