在C++映射中选择随机元素的百分比 我有一个C++映射:STD::MAP/P>

在C++映射中选择随机元素的百分比 我有一个C++映射:STD::MAP/P>,c++,dictionary,random,c++03,C++,Dictionary,Random,C++03,我想从这张地图中选取p百分比的随机元素。这里p是动态的。例如,10%或30%的键:值对来自此映射,但随机拾取。无法使用c++11 最好的方法是什么 多谢各位 将布尔向量初始化为与贴图相同的大小 计算T=map.size*百分比 将向量的前T个元素初始化为true,其余元素初始化为false 随机洗牌向量中的元素 在映射和向量上同时迭代-当向量中对应的索引位置为true时,在映射中指定一个项 示例代码: #include <iostream> #include <map>

我想从这张地图中选取p百分比的随机元素。这里p是动态的。例如,10%或30%的键:值对来自此映射,但随机拾取。无法使用c++11

最好的方法是什么

多谢各位

将布尔向量初始化为与贴图相同的大小 计算T=map.size*百分比 将向量的前T个元素初始化为true,其余元素初始化为false 随机洗牌向量中的元素 在映射和向量上同时迭代-当向量中对应的索引位置为true时,在映射中指定一个项 示例代码:

#include <iostream>
#include <map>
#include <vector>
#include <string>

using namespace std;

void getRandomMapElements(map<string, int>& items, double percentage)
{
    const size_t count = items.size();
    vector<bool> vec;
    vec.resize(count); // all items in vec are "false"

    if (percentage < 0)
    {
        percentage = 0;
    }
    else if (percentage > 1.0)
    {
        percentage = 1.0;
    }

    size_t target = (size_t)(count * percentage); // actual number of items extracted

    // fill up the first TARGET count elements of the vector with true, the rest are kept at false
    for (size_t i = 0; i < target; i++)
    {
        vec[i] = true;
    }

    // shuffle the boolean vector
    for (size_t i = 0; i < count; i++)
    {
        bool val = vec[i];
        size_t swap = rand() % count;
        vec[i] = vec[swap];
        vec[swap] = val;
    }

    // iterate over the vector and map together
    map<string, int>::iterator itor = items.begin();
    for (size_t i = 0; i < count; i++)
    {
        if (vec[i])
        {
            cout << itor->first << " : " << itor->second << endl;
        }
        itor++;
    }
}
使用C++17可以完全满足您的需要,但对于C++98则稍微复杂一些

与c++98兼容的最短代码为:

unsigned pick_below(unsigned n)
{
     // poor distribution:
     return std::rand() % n;
}
std::vector<std::pair<std::string, int> >
sample(const std::map<std::string, int> & data_in,
       unsigned p)
{
 std::vector<std::pair<std::string, int> > shuffled(data_in.begin(), data_in.end());
 for (unsigned i=shuffled.size()  ; i > 1 ; --i)
   std::swap(shuffled[i-1], shuffled[pick_below(i)]);
 shuffled.erase(shuffled.begin() +p, shuffled.end());
}
通过使用第三方随机生成器(如boost::random::mt19937)可以解决问题1


不幸的是,该解决方案的复杂性是平均的,因为下面的pick_不能保证终止,但在任何值p 请澄清随机元素的百分比是多少。要拾取的元素的数量=p*映射的大小/100?您的C++03安装中是否有?征求最佳意见总是征求意见,因此您可能需要澄清这一点。
unsigned pick_below(unsigned n)
{
    unsigned x;
    do {
       x = rand();
    } while (x >= (RAND_MAX - RAND_MAX % n));
    return x % n;
}