php 选择 出现列表,php – 如何从加权列表中选择4个唯一项?

所以我有一个加权项目列表,我想从这个列表中选择4个非重复项目.

Item Weight

Apple 5

Banana 7

Cherry 12

...

Orange 8

Pineapple 50

最有效的方法是什么?我最初的尝试是,如果一个已经被选中的项目出现的话,只需重新选择随后的选秀权……但是对于一个小名单,这可能会导致大量的重新加入.

编辑以澄清:

对于上面的例子,忽略水果D到N,总重量为82.所以先被挑选的机会是:

约6%

B~8.5%

C~14.6%

O~9.8%

P~61%

一旦选择了一个项目,概率就会(应该!)改变.

解决方法:

在你的评论中,你说这是独特的意思:

I don’t want to pick the same item twice.

..并且权重决定了被挑选的可能性.

您需要做的就是确保不挑选重复项,只需从列表中删除最后一个选中的项目,然后再选择下一个项目.是的,这会稍微改变您的权重,但如果您确实需要独特的结果,那么这是正确的统计变化.

另外,我不确定你是如何使用权重来确定候选者的,但我想出了这个算法,它应该用最少的循环来完成这个(并且不需要根据权重填充数组,可能导致非常大的数组,需要int权重等)

我在这里使用了JavaScript,因此很容易在没有服务器的浏览器中看到输出.移植到PHP应该是微不足道的,因为它没有做任何复杂的事情.

常量

var FRUITS = [

{name : "Apple", weight: 8 },

{name : "Orange", weight: 4 },

{name : "Banana", weight: 4 },

{name : "Nectarine", weight: 3 },

{name : "Kiwi", weight: 1 }

];

var PICKS = 3;

function getNewFruitsAvailable(fruits, removeFruit) {

var newFruits = [];

for (var idx in fruits) {

if (fruits[idx].name != removeFruit) {

newFruits.push(fruits[idx]);

}

}

return newFruits;

}

脚本

var results = [];

var candidateFruits = FRUITS;

for (var i=0; i < PICKS; i++) {

// CALCULATE TOTAL WEIGHT OF AVAILABLE FRUITS

var totalweight = 0;

for (var idx in candidateFruits) {

totalweight += candidateFruits[idx].weight;

}

console.log("Total weight: " + totalweight);

var rand = Math.random();

console.log("Random: " + rand);

// ITERATE THROUGH FRUITS AND PICK THE ONE THAT MATCHES THE RANDOM

var weightinc = 0;

for (idx in candidateFruits) {

// INCREMENT THE WEIGHT BY THE NEXT FRUIT'S WEIGHT

var candidate = candidateFruits[idx];

weightinc += candidate.weight;

// IF rand IS BETWEEN LAST WEIGHT AND NEXT WEIGHT, PICK THIS FRUIT

if (rand < weightinc/totalweight) {

results.push(candidate.name);

console.log("Pick: " + candidate.name);

// GET NEXT SET OF FRUITS (REMOVING PICKED FRUIT)

candidateFruits = getNewFruitsAvailable(candidateFruits, candidate.name);

break;

}

}

console.log("CandidateFruits: " + candidateFruits.length);

};

产量

for (var i=0; i < results.length; i++) {

document.write(results[i] + "
");

}

基本策略是为每个水果分配总范围[0,1]的一部分.在第一个循环中,你有这个:

> Apple – 8/20 = 0.0最高0.4

>橙色 – 4/20 = 0.4至0.6

>香蕉 – 4/20 = 0.6至0.8

>油桃 – 3/20 = 0.8至0.95

> Kiwi – 8/20 = 0.95至1.0

该脚本遍历列表中的每个项目,并进行权重计数器.当它到达包含第一个随机的范围时,它会选择该项目,将其从列表中删除,然后根据新的总重量重新计算范围并再次运行.

标签:php,algorithm,random,list,weighted

来源: https://codeday.me/bug/20190610/1210472.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值