Случайное значение из массива по массе в php

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

$fruits = array('20' => 'apple', '40' => 'orange', '40' => 'pear');

Ключи представляют собой процентное соотношение шансов на получение стоимости. Я хотел бы mt_rand() число от 0 до 99 и вернуть значение из $fruit на основе этих процентов.

Очень возможно, я так запутался, потому что не знаю, как объяснить, что я ищу.

Заранее спасибо за помощь.

Изменить: требуется случайное значение из $fruit, исходя из этих шансов:

Я хочу 40% шанс получить апельсин, 40% шанс получить грушу и 80% шанс получить яблоко.

Изменить: Чтобы уточнить, так как многие ответы получили неправильное (или я просто не понимаю их код), мне нужен был результат независимо от того, какой номер я выбираю, а не только 20, 40 или 40.

Ответ 1

Я думаю, что что-то вроде этого сделает то, что вы хотите:

образец

(нажмите кнопку отправки несколько раз на образце, чтобы получить код для повторного выполнения)

$fruits = array('apple' => '20', 'orange' => '40', 'pear' => '40');

$newFruits = array();
foreach ($fruits as $fruit=>$value)
{
    $newFruits = array_merge($newFruits, array_fill(0, $value, $fruit));
}

$myFruit = $newFruits[array_rand($newFruits)];

Это создает массив ($newFruits), который представляет собой числовой индексный массив со 100 элементами. 20 из этих элементов - "яблоко", 40 - "оранжевое", а 40 - "груша". Затем мы выбираем случайный индекс из этого массива. 20 раз из 100 вы получите "яблоко", 40 раз из 100 вы получите "оранжевый", а 40 раз из 100 вы получите "грушу".

Ответ 2

Прежде всего, ваш массив имеет только два элемента (яблоко и груша), потому что груша перезаписывает оранжевый из-за наличия того же ключа. Поэтому используйте обратный порядок. Кроме того, не ставьте кавычки вокруг целых чисел:

$fruits = array('apple' => 20, 'orange' => 40, 'pear' => 40);

Вы должны выбрать случайное число, затем сравнить каждый вес массива плюс сумму предыдущих весов, пока не получите соответствие:

$rand = rand(1,100);
$sum = 0;
$chosenFruit;

foreach ($fruits as $f=>$v) {
    $sum += $v;
    if ( $sum >= $rand ) {
        $chosenFruit = $f;
        break;
    }
}

echo "We have chosen the {$chosenFruit}!";

Вы даже можете сделать процедуру более упругой, заменив значение 100 в функции rand() на вычисленную сумму значений массива $fruits.

Ответ 3

  $key = rand(1,98); // rand() is inclusive of the range, hence 1-98.
  foreach( $fruits as $k => $v){
  if( $k == $key) {
    echo 'Chosen fruit is:' . $v; 
    break;
    } 
  }

Ответ 4

Есть несколько дорог, чтобы спуститься с этим, и они в значительной степени зависят от ваших данных. Используя проценты, 0 - 100, у вас может быть 100 элементов в вашем массиве, каждая из которых соответствует проценту, или вы можете иметь распределение с назначенными значениями (подобно массиву в вашем примере).

Предполагая первое, вы можете использовать:

$key = mt_rand(0, 100);
$fruit = isset($fruits[$key]) ? $fruits[$key] : false;

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

$key = mt_rand(0, 100);
$fruit = false;
foreach ($fruits as $percent => $value) {
    if ($percent <= $key) {
        $fruit = $value;
        break;
    }
}

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

$key = mt_rand(0, 100);
$matches = array();
foreach ($fruits as $percent => $value) {
    if ($percent <= $key) {
        $matches[] = $value;
    }
}
$select = mt_rand(0, count($matches) - 1);
$fruit = $matches[$select];