Picking random element by user defined weights [du

2020-02-13 22:02发布

Possible Duplicate:
Generating random results by weight in PHP?

I have a web application where users can add 1-20 strings of text and assign a weight to them of how often it should show up. The system would then choose a random string based on the defined weights. What is the best way to go about this? Do the range values for the weight for each string matter? Could I just have the user assign a number (0-100) for each string? How would you go about choosing a random string? (Each choice doesn't worry about what was chosen before, every string has the same odds (based on weight) of being chosen at the start of each call).

3条回答
别忘想泡老子
2楼-- · 2020-02-13 22:37

I use this function in several PHP game engines:

<?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;
}

Usage

Suppose I have the user weights in an associative array where each string points to its weight:

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

If I wanted to pull a string based on weight, I'd do this:

$weights = array_values($weighted_strings);
$strings = array_keys($weighted_strings);
$index = getBucketFromWeights($weights);
$selectedString = $strings[$index];
查看更多
地球回转人心会变
3楼-- · 2020-02-13 22:37

Here is a simple implementation:

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;
}

With this function you can specify how many unique weighted random elements you want (IDEOne).

查看更多
够拽才男人
4楼-- · 2020-02-13 22:51

Nice answer is provided here, but there is a way to save on loockup loop. Faster way to select random value from array. Actually Idea is the same, just works faster as a simple loop.

查看更多
登录 后发表回答