SO,
问题
众所周知pseudo-random numbers。 “伪”实际上意味着,尽管它们通常是随机的(即不可预测的),但它们仍然是相同的,其中使用相同的发生器初始值。例如,在PHP中有mt_srand()函数可以做到这一点。例如:
mt_srand(1);
var_dump(mt_rand(), mt_rand(), mt_rand());
- 无论如何,我们将启动我们的脚本多少次:生成的三个数字将始终相同。
现在,我的问题是如何做同样的事情 - 但是为了改组阵列。即我想创建一个函数,它将接受shuffle和 seed 的输入数组。在相同的种子值内,洗牌必须具有连续的相同顺序。即让我们调用该函数shuffleWithSeed()
- 然后跟随应该适用于每个脚本启动:
$input = ['foo', 'bar', 'baz'];
$test = shuffleWithSeed($input, 1000);//1000 is just some constant value
var_dump($test); //let it be ['bar', 'foo', 'baz']
$test = shuffleWithSeed($test, 1000);
var_dump($test); //let it be ['baz', 'foo', 'bar']
$test = shuffleWithSeed($test, 1000);
var_dump($test); //let it be ['baz', 'bar', 'foo']
//...
-i.e。无论我们为阵列进行多少次洗牌 - 我希望下一个脚本启动顺序在一个seed
值内始终相同。
我的方法
我想到了这个算法:
seed
N
个随机数,其中N
是$input
个成员的数量$input
键。我已经实现了这个:
function shuffleWithSeed(array $input, $seed=null)
{
if(!isset($seed))
{
shuffle($input);
return $input;
}
if(!is_int($seed))
{
throw new InvalidArgumentException('Invalid seed value');
}
mt_srand($seed);
$random = [];
foreach($input as $key=>$value)
{
$random[$key] = mt_rand();
}
asort($random);
$random = array_combine(array_keys($random), array_values($input));
ksort($random);
return $random;
}
- 现在,也找到Fisher-Yates算法 - 但不确定它是否可以与伪随机数一起使用(即使用种子)
问题
正如你所看到的,我在我的功能中做了两种 - 首先是值,第二是按键。
答案 0 :(得分:9)
这是我刚才实现的功能的复制和粘贴,用于此目的:
/**
* Shuffles an array in a repeatable manner, if the same $seed is provided.
*
* @param array &$items The array to be shuffled.
* @param integer $seed The result of the shuffle will be the same for the same input ($items and $seed). If not given, uses the current time as seed.
* @return void
*/
protected function seeded_shuffle(array &$items, $seed = false) {
$items = array_values($items);
mt_srand($seed ? $seed : time());
for ($i = count($items) - 1; $i > 0; $i--) {
$j = mt_rand(0, $i);
list($items[$i], $items[$j]) = array($items[$j], $items[$i]);
}
}
它实现了一个带有种子随机数生成器的简单Fisher-Yates shuffle。