получите случайное значение из массива PHP, но сделайте его уникальным
Я хочу выбрать случайное значение из массива, но сохранить его уникальным как можно дольше.
например, если я выбираю значение в 4 раза из массива из 4 элементов, выбранное значение должно быть случайным, но каждый раз разные.
Если я выбираю его 10 раз из того же массива из 4 элементов, то, очевидно, некоторые значения будут дублироваться.
У меня есть это прямо сейчас, но я все еще получаю повторяющиеся значения, даже если цикл выполняется 4 раз:
$arr = $arr_history = ('abc', 'def', 'xyz', 'qqq');
for($i = 1; $i < 5; $i++){
if(empty($arr_history)) $arr_history = $arr;
$selected = $arr_history[array_rand($arr_history, 1)];
unset($arr_history[$selected]);
// do something with $selected here...
}
8 ответов
вы почти правы. Проблема была в unset($arr_history[$selected]);
линии. Значение $selected
не является ключом, но на самом деле значением, поэтому unset не будет работать.
чтобы сохранить его таким же, как у вас там:
<?php
$arr = $arr_history = array('abc', 'def', 'xyz', 'qqq');
for ( $i = 1; $i < 10; $i++ )
{
// If the history array is empty, re-populate it.
if ( empty($arr_history) )
$arr_history = $arr;
// Select a random key.
$key = array_rand($arr_history, 1);
// Save the record in $selected.
$selected = $arr_history[$key];
// Remove the key/pair from the array.
unset($arr_history[$key]);
// Echo the selected value.
echo $selected . PHP_EOL;
}
или пример с несколькими строками меньше:
<?php
$arr = $arr_history = array('abc', 'def', 'xyz', 'qqq');
for ( $i = 1; $i < 10; $i++ )
{
// If the history array is empty, re-populate it.
if ( empty($arr_history) )
$arr_history = $arr;
// Randomize the array.
array_rand($arr_history);
// Select the last value from the array.
$selected = array_pop($arr_history);
// Echo the selected value.
echo $selected . PHP_EOL;
}
как насчет перетасовки массива, и выталкивание детали.
, когда pop
возвращает null
обнулить массив.
$orig = array(..);
$temp = $orig;
shuffle( $temp );
function getNextValue()
{
global $orig;
global $temp;
$val = array_pop( $temp );
if (is_null($val))
{
$temp = $orig;
shuffle( $temp );
$val = getNextValue();
}
return $val;
}
конечно, вы захотите инкапсулировать это лучше, и сделать лучшую проверку, и другие такие вещи.
Php имеет собственную функцию shuffle
который вы можете использовать для случайного порядка элементов в массиве. Так что насчет этого?
$arr = ('abc', 'def', 'xyz', 'qqq');
$random = shuffle($arr);
foreach($random as $number) {
echo $number;
}
<?php
$array = array('abc', 'def', 'xyz', 'qqq');
$numRandoms = 3;
$final = array();
$count = count($array);
if ($count >= $numRandoms) {
while (count($final) < $numRandoms) {
$random = $array[rand(0, $count - 1)];
if (!in_array($random, $final)) {
array_push($final, $random);
}
}
}
var_dump($final);
?>
ключ != значение, используйте это:
$index = array_rand($arr_history, 1);
$selected = $arr_history[$index];
unset($arr_history[$index]);
Я сделал это, чтобы создать случайные 8-значный пароль для пользователей:
$characters = array(
"A","B","C","D","E","F","G","H","J","K","L","M",
"N","P","Q","R","S","T","U","V","W","X","Y","Z",
"a","b","c","d","e","f","g","h","i","j","k","m",
"n","p","q","r","s","t","u","v","w","x","y","z",
"1","2","3","4","5","6","7","8","9");
for( $i=0;$i<=8;++$i ){
shuffle( $characters );
$new_pass .= $characters[0];
}
Если вас не волнует, какие конкретные значения находятся в массиве, вы можете попытаться реализовать линейный конгруэнтный генератор для генерации всех значений в массиве.
Википедия перечисляет некоторые значения, которые вы можете использовать, и правила выбора значений для алгоритма LCG, поскольку алгоритм LCG является детерминированным, гарантируется, что он не повторит ни одного значения до длины периода.
после заполнения массив с этими уникальными номерами, вы можете просто получить номера в массиве 1 на 1 в порядке.
легкий и чистый:
$colors = array('blue', 'green', 'orange');
$history = $colors;
function getColor($colors, &$history){
if(count($history)==0)
$history = $colors;
return array_pop( $history );
}
echo getColor($colors, $history);