class WeightElement {
private $_item;
private $_weight;
private $min;
private $max;
public function __construct($item, $weight){
$this->_item = $item;
$this->_weight = $weight;
}
public function setMin($min){
$this->min = $min;
}
public function setMax($max){
$this->max = $max;
}
public function getMin(){
return $this->min;
}
public function getMax(){
return $this->max;
}
public function getItem(){
return $this->_item;
}
}
class WeightRandom {
private $items = array();
function __construct()
{
# code...
}
public function addItem($item, $weight = 1){
$this->items[$item] = $weight;
}
public function getItem(){
if (empty($this->items)) {
return '';
}
$min = 0;
$max = 0;
$elements = array();
foreach ($this->items as $key => $value) {
$max = $min + $value;
$element = new WeightElement($key, $value);
$element->setMin($min);
$element->setMax($max);
$elements[] = $element;
$min = $max;
}
$rv = rand(0, array_sum($this->items)-1);
return $this->getElementByRandomValue($elements, $rv);
}
protected function getElementByRandomValue($elements, $rv){
$start = 0;
$end = count($elements) - 1;
$index = (int)(count($elements) / 2);
while (true) {
$element = $elements[$index];
if ($rv < $element->getMin()) {
$end = $index - 1;
} elseif($rv >= $element->getMax()){
$start = $index + 1;
} else {
return $element->getItem();
}
$index = (int)(($start + $end) / 2);
}
}
}
$random = new WeightRandom();
$random->addItem('li', 5);
$random->addItem('wang', 4);
$random->addItem('zhao', 3);
$random->addItem('sun', 2);
$random->addItem('qian', 1);
$array = array();
for ($i=0; $i < 1500; $i++) {
$item = $random->getItem();
$array[$item] = isset($array[$item]) ? $array[$item] + 1 : 1;
}
arsort($array);
error_log(var_export($array,true));
结果:
[22-May-2018 15:14:13 Etc/GMT-8] array (
'li' => 501,
'wang' => 400,
'zhao' => 295,
'sun' => 201,
'qian' => 103,
)