如何从数组中获取一个不太随机的值?

How to fetch a not so random value from an array?

想法

在工作中,我们有一项没人愿意做的任务。所以我尝试制作一个脚本,从数组中随机选择一个人并显示他们的名字。但是,当我们有实习生时,我们希望 him/her 比其他人更频繁地出现。

请记住,这只是在玩弄代码。

代码

<?php
if (!isset($_COOKIE['names'])) {
    // Prepare initial array
    $names = array(
        'John Doe' => 10,
        'Jane Doe' => 10,
        'Mike Doe' => 10,
        'Gina Doe' => 10,
        'Anne Doe' => 10,
        'George Doe' => 10,
        'Jack Doe' => 10,
    );

    // Create cookie
    setcookie('names', serialize($names), time()+28800);
}

$names = unserialize($_COOKIE['names']);

$randomArray = array();
foreach ($names as $name => $probability) {
    if ($probability > 1) {
        foreach (range(1, $probability) as $v) {
            $randomArray[] = $name;
        }
    } else {
        $names[$name] = 10;
    }
}

$selected = $randomArray[array_rand($randomArray)];
if (array_key_exists($selected, $names)) {
    if ($names[$selected] > 1) {
        $names[$selected]--;
    }
    setcookie('names', serialize($names), time()+28800);
    echo $selected;
}

通过查看这段代码,我想您会明白大概的意思。通过提高概率,人们的名字会更频繁地出现。

问题

当概率来到1时,我把它设置回10。但不知怎的,这感觉不对。我不是微积分奇迹,但我的头脑可以弄清楚这是不对的。另外,我写的这段代码感觉一点也不高效。在我看来循环太多了。

我想请您看看我的代码并告诉我我做错了什么以及我可以做些什么来改进它。也欢迎提出建议等。

快速简单/懒惰的方法是添加更多你想要的人的实例以增加获得任务的机会:

$names = array(
    'John Doe',
    'Jane Doe',
    'Mike Doe',
    'Gina Doe',
    'Anne Doe',
    'George Doe',
    'Jack Doe',//intern - 50% of getting selected
    'Jack Doe',
    'Jack Doe',
    'Jack Doe',
    'Jack Doe',
    'Jack Doe',
);
var_dump(array_rand($names));

编辑

所以你的代码生成了上面的内容,你想简化它:

$names = array(
    'John Doe' => 1,
    'Jane Doe' => 1,
    'Mike Doe' => 2,
    'Gina Doe' => 3,
    'Anne Doe' => 5,
    'George Doe' => 8,
    'Jack Doe' => 13,
);
$randomNames = array();
foreach($names as $name => $probability) {
    do {
        $randomNames[] = $name;
    } while (--$probability > 0);
}
var_dump($randomNames[array_rand($randomNames)]);

编辑 2

我刚刚弄清楚 COOKIE 正在做什么。降低每个名字出现的概率:

session_start();
// instantiate array
$names = array(
    'John Doe' => 1,
    'Jane Doe' => 1,
    'Mike Doe' => 2,
    'Gina Doe' => 3,
    'Anne Doe' => 5,
    'George Doe' => 8,
    'Jack Doe' => 13,
);

// if array exists in session, use that
if(array_key_exists('names',$_SESSION)) {
    $names = unserialize($_SESSION['names']);
}

// Add each name x times where 'x' is the value of $probability
$randomNames = array();
foreach($names as $name => $probability) {
    do {
        $randomNames[] = $name;
    } while (--$probability > 0);
}

// reduce probability by one. If value is less than, or equal to, 0 then reset probability yo 10
$chosen = $randomNames[array_rand($randomNames)];
$names[$chosen]--;
if($names[$chosen] <= 0) {
    $names[$chosen] = 10;
}

// Save array into session for next run
$_SESSION['names'] = serialize($names);

var_dump($chosen,$names);

我会 select 一个随机数来确定它是 "the group" 还是 "the poor intern",如果是 "the group",则得到另一个随机数来确定哪个成员组.

我假设数组中的数字是概率的权重 - 即使您已将它们全部设置为 10...

因此,要从数组中进行选择,您需要诸如...

$weight_total = 0;
foreach ($names as $weight) 
  $weight_total += $weight;

$random_number = rand(1, $weight_total); // Random number between 1 and $weight_total

$running_total = 0;
foreach ($names as $name => $weight) {
  if ($random_number > $running_total && $random_number <= ($running_total + $weight)) {
     echo $name; 
     break;
  }
  $running_total += $weight;
}

那就把实习生的权重设置得比其他人高一些就好了