我希望有人能帮我解决这个问题。我想拿一个有序的 php 数组并随机"摇晃"它一点以更改顺序,但保留一些原始的整体结构。
想象一下,你有一盘彩色亮片,构成了一幅房子的图片。如果你稍微摇晃一下托盘,那么亮片就会移动,但是,根据你摇晃的程度,你仍然会保留一些房子的原始结构——它会更模糊。这就是我想用 php 数组做的事情。
我举个例子。假设我有以下数组:
$Array=Array(
1=>15,
2=>14,
3=>13,
4=>12,
5=>11,
6=>10,
7=>9,
8=>8,
9=>7,
10=>6,
11=>5,
12=>4,
13=>3,
14=>2,
15=>1);
我希望能够稍微摇晃一下,给出类似的东西:
$Array=Array(
1=>13,
2=>15,
3=>12,
4=>14,
5=>11,
6=>8,
7=>7,
8=>10,
9=>5,
10=>6,
11=>9,
12=>4,
13=>2,
14=>1,
15=>3);
该顺序已部分随机化,但总体下降趋势从 15 到 1 仍然存在。我希望这是有道理的。
除非我弄错了,否则我认为 php 中没有本机函数可以做到这一点。但是有谁知道这如何实现?
与其使用 shuffle()
或 array_shuffle()
等经过优化以获得尽可能多的随机结果的函数,不如编写自己的算法:
尝试一下"冒泡"策略:
- 通过交换一对
- 又一对来交换数组的元素。
- 始终从数组中成对选取相邻元素。
- 随机化为每个迭代步骤选择的现有对。
- 您可以限制迭代次数,从而限制结果的总"随机性"。
这应该比严格随机化更好地保留元素的粗略位置,因为元素在每次迭代中只能移动一个步骤。所以应该保持大趋势。多少取决于您执行的迭代次数。
下面是一个(非常简单的)示例实现:
#!/usr/bin/php
<?php
// the input array, just as you specified it
$input=array(
1=>15,
2=>14,
3=>13,
4=>12,
5=>11,
6=>10,
7=>9,
8=>8,
9=>7,
10=>6,
11=>5,
12=>4,
13=>3,
14=>2,
15=>1
);
// the algorithm itself, a 'bubbling' function
function array_bubble (&$collection, $limit) {
for ($i=1; $i<=$limit; $i++) {
$pos=rand(min(1,sizeof($collection)-1);
$help=$collection[$pos];
$collection[$pos] =$collection[$pos+1];
$collection[$pos+1]=$help;
}
return $collection;
} // function array_bubble
// here the algorithm is called and the result printed
// note that the '20' in there is the number of iterations. Try changing it!
print_r(array_bubble($input,20));
?>
该脚本生成如下输出:
Array
(
[1] => 11
[2] => 15
[3] => 13
[4] => 8
[5] => 14
[6] => 12
[7] => 9
[8] => 10
[9] => 5
[10] => 6
[11] => 7
[12] => 4
[13] => 1
[14] => 3
[15] => 2
)
arkascha 提到的冒泡策略的替代方案,您可以遍历数组,并生成一个具有高斯/正态分布的随机数来交换当前元素。也许在代码中描述得更好(未经测试):
function swap (&$arr, $a, $b) {
$tmp=$arr[$a];
$arr[$a]=$arr[$b];
$arr[$b]=$tmp;
}
for ($i = 0; $i < count($arr); $i++) {
$diff = round(stats_rand_gen_normal(0, 3));
$j = max(0, min(count($arr), $i + $diff));
swap($arr, $i, $j);
}
这应该只需要一次通过;抖动的平均值和标准偏差应该大致是要stats_rand_gen_normal的参数。