基于用户投票的排名算法:Delicious和Hacker News (Python、Redis简单实现)
基于用户投票的排名算法(一):Delicious和Hacker News
来自阮一峰的博客
具体思想参照其博客的分析
一、Delicious
最直觉、最简单的算法,莫过于按照单位时间内用户的投票数进行排名。得票最多的项目,自然就排在第一位。 下面使用Python、Redis简单的实现一些核心思想
# -*- coding: utf-8 -*-
import redis
MAX_EXPIRE_TIME = 60
cache = redis.Redis(host='localhost',port=6379,db=0)
"""
all_votes:{
'video_1': x,
'video_2': y,
....
}
"""
def user_vote(video_id):
key = 'video_%d', video_id
cache.hincrby('all_votes', key, 1) # video_xx 的 value(即投票数加1)
def get_rank():
""""
脚本每隔 MAX_EXPIRE_TIME分钟运行一次,作为这段时间内投票数的统计
"""
rank_dic = cache.hgetall('all_votes')
rank_list = rank_dic.item().sort(key = lambda k: k[1]) # 根据video_xx的 value(投票数) 排名
cache.delete('all_votes') # 清除这次统计
return rank_list
二、Hacker News
每个帖子前面有一个向上的三角形,如果你觉得这个内容很好,就点击一下,投上一票。根据得票数,系统自动统计出热门文章排行榜。但是,并非得票最多的文章排在第一位,还要考虑时间因素,新文章应该比旧文章更容易得到好的排名。
其中,
- P表示帖子的得票数,减去1是为了忽略发帖人的投票。
- T表示距离发帖的时间(单位为小时),加上2是为了防止最新的帖子导致分母过小(之所以选择2,可能是因为从原始文章出现在其他网站,到转贴至Hacker News,平均需要两个小时)。
- G表示”重力因子”(gravityth power),即将帖子排名往下拉的力量,默认值为1.8,后文会详细讨论这个值。
从这个公式来看,决定帖子排名有三个因素:
# -*- coding: utf-8 -*-
import time
import redis
cache = redis.Redis(host='localhost',port=6379,db=0)
G = 1.8
"""
video_x:
{
'votes': 得票
'created': 创建时间
'score'
}
"""
def set_hot(video_id):
key = 'video_%d', video_id
value = cache.hgetall(key)
P = value.get('votes')
T = (time.time() - value.get('created')) / (60 * 60)
Score = (P - 1) / ((T + 2) ** G)
cache.hset(key, 'score', Score)
知道了算法的构成,就可以调整参数的值,以适用你自己的应用程序。