我有一个Web应用程序,用户可以在其中添加1-20个文本字符串,并为它们指定显示频率的权重。然后,系统将根据定义的权重选择随机字符串。最好的方法是什么?每个字符串的重量范围值是否重要?我可以让用户为每个字符串分配一个数字(0-100)吗?你会如何选择随机字符串? (每个选择都不担心之前选择的内容,每个字符串在每次调用开始时都有相同的赔率(基于权重))。
答案 0 :(得分:6)
我在几个PHP游戏引擎中使用此函数:
<?php
/**
* @param array $values - just the weights
* @return integer A number between 0 and count($values) - 1
*/
function getBucketFromWeights($values) {
$total = $currentTotal = $bucket = 0;
$firstRand = mt_rand(1, 100);
foreach ($values as $amount) {
$total += $amount;
}
$rand = ($firstRand / 100) * $total;
foreach ($values as $amount) {
$currentTotal += $amount;
if ($rand > $currentTotal) {
$bucket++;
}
else {
break;
}
}
return $bucket;
}
<强>用法强>
假设我在关联数组中有用户权重,其中每个字符串指向其权重:
$weighted_strings = array(
"important string" => 100,
"terrible string" => 10,
"never string" => 0,
// etc
);
如果我想根据体重拉弦,我会这样做:
$weights = array_values($weighted_strings);
$strings = array_keys($weighted_strings);
$index = getBucketFromWeights($weights);
$selectedString = $strings[$index];
答案 1 :(得分:1)
这是一个简单的实现:
function Probability($data, $number = 1)
{
$result = array();
if (is_array($data) === true)
{
$data = array_map('abs', $data);
$number = min(max(1, abs($number)), count($data));
while ($number-- > 0)
{
$chance = 0;
$probability = mt_rand(1, array_sum($data));
foreach ($data as $key => $value)
{
$chance += $value;
if ($chance >= $probability)
{
$result[] = $key; unset($data[$key]); break;
}
}
}
}
return $result;
}
使用此功能,您可以指定所需的唯一加权随机元素数(IDEOne)。
答案 2 :(得分:-1)
这里提供了很好的答案,但有一种方法可以节省查找循环。加快select random value from array的方式。实际上Idea是一样的,只是作为一个简单的循环工作得更快。