Выбор случайного элемента по пользовательским весам

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

У меня есть веб-приложение, в котором пользователи могут добавлять 1-20 строк текста и присваивать им вес, как часто он должен появляться. Затем система выбирает случайную строку, основанную на определенных весах. Каков наилучший способ сделать это? Значения диапазона для веса каждой строки? Могу ли я просто назначить пользователю номер (0-100) для каждой строки? Как бы вы выбрали случайную строку? (Каждый выбор не беспокоится о том, что было выбрано раньше, каждая строка имеет одинаковые шансы (по весу) выбора в начале каждого вызова).

Solutions Collecting From Web of "Выбор случайного элемента по пользовательским весам"

Я использую эту функцию в нескольких игровых движках PHP:

<?php /** * @param array $values - just the weights * @return integer A number between 0 and count($values) - 1 */ function getBucketFromWeights($values) { $total = $currentTotal = $bucket = 0; $firstRand = mt_rand(1, 100); foreach ($values as $amount) { $total += $amount; } $rand = ($firstRand / 100) * $total; foreach ($values as $amount) { $currentTotal += $amount; if ($rand > $currentTotal) { $bucket++; } else { break; } } return $bucket; } 

Применение

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

 $weighted_strings = array( "important string" => 100, "terrible string" => 10, "never string" => 0, // etc ); 

Если бы я хотел потянуть строку по весу, я бы сделал это:

 $weights = array_values($weighted_strings); $strings = array_keys($weighted_strings); $index = getBucketFromWeights($weights); $selectedString = $strings[$index]; 

Вот простая реализация:

 function Probability($data, $number = 1) { $result = array(); if (is_array($data) === true) { $data = array_map('abs', $data); $number = min(max(1, abs($number)), count($data)); while ($number-- > 0) { $chance = 0; $probability = mt_rand(1, array_sum($data)); foreach ($data as $key => $value) { $chance += $value; if ($chance >= $probability) { $result[] = $key; unset($data[$key]); break; } } } } return $result; } не function Probability($data, $number = 1) { $result = array(); if (is_array($data) === true) { $data = array_map('abs', $data); $number = min(max(1, abs($number)), count($data)); while ($number-- > 0) { $chance = 0; $probability = mt_rand(1, array_sum($data)); foreach ($data as $key => $value) { $chance += $value; if ($chance >= $probability) { $result[] = $key; unset($data[$key]); break; } } } } return $result; } 

С помощью этой функции вы можете указать, сколько уникальных взвешенных случайных элементов вы хотите ( IDEOne ).

Хороший ответ предоставляется здесь, но есть способ сохранить цикл loockup. Более быстрый способ выбора случайного значения из массива . На самом деле идея одинакова, просто работает быстрее, как простой цикл.