我需要一个类似于 shuffle 的函数来随机化数组,不同之处在于每个元素都有不同的机会。
例如,考虑以下数组:
$animals = array('elephant', 'dog', 'cat', 'mouse');
大象比狗更有机会进入第一个索引。狗的机会比猫高等等。例如,在这个特定的例子中,大象可能有 40% 的机会获得第一位置,30% 的机会获得第二位置,20% 的机会获得第三位置,10% 的机会获得最后位置。
因此,在打乱之后,原始数组中的第一个元素将更有可能(但不确定)位于第一个位置,而最后一个元素则更有可能位于最后一个位置。
最佳答案
正常的随机播放可以像这样实现
- 在一定范围内随机掉落元素
- 从左到右拾取它们
我们可以调整下降步骤,将每个元素不下降到整个范围,而是下降到某个滑动窗口。令N
为数组中元素的数量,窗口宽度为w
,我们将在每一步将其移动off
。那么 off*(N-1) + w
将是范围的总宽度。
这是一个函数,它会扭曲元素的位置,但不是完全随机的。
function weak_shuffle($a, $strength) {
$len = count($a);
if ($len <= 1) return $a;
$out = array();
$M = mt_getrandmax();
$w = round($M / ($strength + 1)); // width of the sliding window
$off = ($M - $w) / ($len - 1); // offset of that window for each step.
for ($i = 0; $i < $len; $i++) {
do {
$idx = intval($off * $i + mt_rand(0, $w));
} while(array_key_exists($idx, $out));
$out[$idx] = $a[$i];
}
ksort($out);
return array_values($out);
}
$strength = 0
~正常洗牌。$strength = 0.25
~您想要的结果(大象
为 40.5%、25.5%、22%、12%)$strength = 1
第一项永远不会在最后一项之后。$strength >= 3
数组实际上从未被打乱
测试 Playground :
$animals = array( 'elephant', 'dog', 'cat', 'mouse' );
$pos = array(0,0,0,0);
for ($iter = 0; $iter < 100000; $iter++) {
$shuffled = weak_shuffle($animals, 0.25);
$idx = array_search('elephant', $shuffled);
$pos[$idx]++;
}
print_r($pos);
关于php - 如何在php中实现特殊的shuffle功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9811562/