2016-07-05 1 views
3

У меня есть массив булевых, из которого я хочу выбрать случайный индекс, значение которого истинно и значение false.Выберите случайный индекс массива с условием на значение

Я могу, конечно, сделать это с помощью грубой силы, выбирая индексы, пока я не ударил одного, значение которого верно:

$arr = array(true, false, false, true, false, true); 

var_dump($arr); 

$i = array_rand($arr); 
while(!$arr[$i]) 
{ 
    $i = array_rand($arr); 
} 
$arr[$i] = false; 

var_dump($arr); 

Это создает что-то вроде этого, где четвертый элемент был изменен.

array(6) { 
    [0]=> 
    bool(true) 
    [1]=> 
    bool(false) 
    [2]=> 
    bool(false) 
    [3]=> 
    bool(true) 
    [4]=> 
    bool(false) 
    [5]=> 
    bool(true) 
} 

array(6) { 
    [0]=> 
    bool(true) 
    [1]=> 
    bool(false) 
    [2]=> 
    bool(false) 
    [3]=> 
    bool(false) 
    [4]=> 
    bool(false) 
    [5]=> 
    bool(true) 
} 

Однако, я должен выполнить эту операцию несколько раз со значительно большим массивом. В какой-то момент массив почти полностью ложный, и в этом случае метод грубой силы довольно неэффективен.

Есть ли более элегантный метод решения этой проблемы? Любая функция array_rand(), где я могу дать предварительное условие?

+0

Вы планируете запустить это в цикле или что-то подобное что будет делать каждую «истинную» запись в какой-то момент? –

ответ

2
$arr = array(true,true,false,false,true,false); 

$res = array_keys($arr, true); 

var_dump($res); // returns 0,1,4 

echo $res[array_rand($res)]; //echo one of the indexes that is true 

Приведенный выше код возвращает индексы истинных значений $ arr в $ res.

https://3v4l.org/CG1v2

Edit. Для того, чтобы затем установить один из $ Arr индексов как ложь вы должны:

$arr[$res[array_rand($res)]] = false; // will set one as false. 

Looping эти две строки, в конечном счете установить все индексы к ложным:

$res = array_keys($arr, true); 
$arr[$res[array_rand($res)]] = false; 
1

Вы можете использовать следующий код:

$arr = array(true, false, false, true, false, true); 

$randTrueIndex = array_rand(array_filter($arr, function($item) { 
    return $item; 
})); 

$arr[$randTrueIndex] = false; 
0

Самый простой способ сделать это, не теряя работу было бы создать случайную перестановку индексов массива. Knuth shuffle (также известный как Fisher-Yates shuffle) должен работать превосходно.

Другим вариантом для некоторых приложений является выбор генератора, который создает значения в требуемом диапазоне без повторения или с относительно небольшим количеством выбросов (значения, выходящие за пределы целевого диапазона). Например, все обладают тем свойством, что любой младший n бит цикл с периодом 2^n. Выберите первую мощность в два, что не меньше, чем размер вашего массива, и вы будете генерировать меньше, чем один потраченный впустую номер для каждого хорошего в среднем.

+1

Я думал о перестановках. Но поскольку вначале массив не совсем прав, кажется, что нет способа предварительно выбрать истинные индексы в первую очередь. Спасибо, что упомянул генераторы. Я помню это. – Sebastian

+0

@Sebastian: В этом случае вы можете выбрать индексы истинных записей в массив и перетасовать их ... I.e. в основном, что написал Исмаил. – DarthGizka

Смежные вопросы