使更多近期项目更容易被绘制

时间:2010-06-02 15:59:40

标签: php sql algorithm random

数据库中有几百本书记录,每条记录都有一个发布时间。在网站的主页上,我需要编写一些代码来随机挑选10本书并将它们放在那里。要求是新书需要有更高的展示机会。

由于时间是整数,我这样想是为了计算每本书的概率:

Probability of a book to be drawn = (current time - publish time of the book) / ((current time - publish time of the book1) +  (current time - publish time of the book1) + ... (current time - publish time of the bookn))

在绘制一本书之后,下一轮循环将从分母中减去(当前时间 - 书的发布时间)并重新计算每本剩余书籍的概率,循环一直持续到10本书已经绘制。

这个算法是否正确?

顺便说一句,该网站是用PHP编写的。

如果您有更好的算法,请随意提出一些PHP代码。

非常感谢大家。

2 个答案:

答案 0 :(得分:1)

首先,我认为你的公式将保证早期的书籍被选中。尝试根据以下内容设置初始概率:

年龄 - 自出版以来的日子

最大(年龄) - 样本中最早的书

书籍时代(i) - 书的年龄我

... Prob(i)= [Max(age)+ e - Book Age(i)] /所有i的总和[Max(age)+ e - Book age(i)]

值e确保最旧的书籍有被选中的概率。既然已经完成了,您可以随时重新计算任何样本的概率。

现在你必须找到一种采用UNBIASED方式挑选书籍。可能最好的方法是使用上面的方法计算累积分布,然后选择一个均匀的(0,1)r.v.找到那个r.v.在累积分布中并选择离它最近的书。

无法帮助您进行编码。合理?

答案 1 :(得分:1)

这是一个非常相似的问题可能会有所帮助:Random weighted choice解决方案是在C#中,但代码非常易读且接近PHP语法,因此应该很容易适应。

例如,以下是在MySQL中如何做到这一点:

首先计算所有书籍的总年龄并将其存储在MySQL用户变量中:

SELECT SUM(TO_DAYS(CURDATE())-TO_DAYS(publish_date)) FROM books INTO @total;

然后随机选择书籍,按年龄加权:

SELECT book_id FROM (
  SELECT book_id, TO_DAYS(CURDATE())-TO_DAYS(publish_date) AS age FROM books
) b
WHERE book_id NOT IN (...list of book_ids chosen so far...)
  AND RAND()*@total < b.age AND (@total:=@total-b.age)
ORDER BY b.publish_date DESC
LIMIT 10;

请注意,@total只有在书籍通过随机选择测试时才会减少,因为AND表达式会短路。

不保证一次性选择10本书 - 甚至不保证在给定的通行证上选择任何书籍。所以你必须重新开始第二步,直到找到10本书。 @total变量保留其减少的值,因此您无需重新计算它。