我得到一个大的向量,它本身包含特定数据类型的向量,例如template <typename Tuple>
auto myget(Tuple&& t)
{
return std::get<0>(std::forward<Tuple>(t));
}
template <typename Tuple>
void consume_tuple_first(Tuple&& t)
{
consume(myget(std::forward<Tuple>(t)));
}
。我试图从foo中检索一个随机元素foo [idx],使std::vector<std::vector<double> > foo
非空或分别为foo[idx]
。
我的天真猜测是从foo[idx].empty() == false
中选择随机元素,直到我的约束foo
得到满足。
然而,foo[idx].empty() == false
非常稀疏地填充非空向量的情况很可能。因此,我的方法很可能会非常缓慢。
是否有更好的方法或者我应该考虑完全不同的数据结构?
答案 0 :(得分:6)
使用非空元素的索引维护辅助向量,并从那里获取随机元素
答案 1 :(得分:2)
您可以构建非空元素的索引:
std::vector<std::vector<double> > foo;
std::vector<decltype (foo)::iterator> nonempty;
for (auto it = foo.begin(); it != foo.end; ++it)
{
if (! it->empty())
{
nonempty.push_back(it);
}
}
std::random_device rd;
// random-number engine used (Mersenne-Twister in this case)
std::mt19937 rng(rd());
// create a guaranteed unbiased index (unlike using modulo on rand)
std::uniform_int_distribution<size_t> uni_idx_dist(0,nonempty.size() - 1);
auto &random_nonempty = *nonempty[uni_idx_dist(rng)];
答案 2 :(得分:0)
您可以先提取非空的索引,然后选择一个:
std::vector<int> ind;
for (int i = 0; i < foo.size(); i++){
if (! foo[i].empty()) {
ind.push_back(i);
}
}
int i = rand() % int.size();
return int[i];
答案 3 :(得分:0)
您可以构建非空向量的引用向量。
{{1}}
答案 4 :(得分:0)
这里有几个问题:
vector
人口稀少vector
of vector
s is wateful 要解决问题 1 我建议使用map<size_t, vector<double>> foo
这将允许您使用非线性指数,但它不会要求人口干预空vector
的。这里选择一个随机填充元素只涉及推进迭代器以指向适当的元素。例如,result
将成为pair
中随机键值foo
的常量:
const auto idx = foo.empty() ? 0U : std::mt19937{std::random_device{}()}() % size(foo);
const auto result = next(cbegin(foo), idx);
1 和 2 的解决方案会更精细,因为我建议一起取消vector
multimap<size_t, double> foo
这包含map
解决方案的所有好处,但权衡是密钥必须使用upper_bound
进行迭代。此外,由于multimap
未存储密钥计数,因此size_t keyCount
需要与multimap
一起维护。或者假设它是一个临时初始化为0U
,可能在需要时浪费地找到它:for(auto it = cbegin(foo); it != cend(foo); it = foo.upper_bound(it->first)) ++keyCount;
使用keyCount
我们可以再次找到result
这里将是与随机密钥匹配的第一个元素的const-iterator:
int idx = keyCount == 0U ? 0 : std::mt19937{std::random_device{}()}() % keyCount;
auto result = cbegin(foo);
while(idx-- > 0) result = foo.upper_bound(result->first);