根据歌曲评分播放歌曲
0x01 摘要
有若干首歌曲,每首歌曲都有评分(0-10)。现要求做一个歌曲播放功能,每首歌被选到的概率和歌曲评分成正比。比如[{“name”: “真的爱你”, “score”: 9.5}]播放概率/[{“name”: “再见理想”, “score”: 9.2}] 约等于 1.03。作者用python写了一份代码,仅供参考。
0x02 数据存放
歌曲信息数据是类似以下格式存放在musics.txt中:
music_name | score |
---|---|
真的爱你 | 9.5 |
再见理想 | 9.2 |
光辉岁月 | 9.3 |
无尽空虚 | 9.3 |
不再犹豫 | 9.8 |
海阔天空 | 9.4 |
最炫民族风 | 8.5 |
老鼠爱大米 | 8.4 |
0x03 方案思路
要求播放歌曲的概率和豆瓣评分成正比,自然想到要将每首歌曲的播放评分和所有歌曲的总评分建立关系,具体来说就是:
歌曲播放概率=歌曲评分/总评分
这就是一种归一化的思想。
0x04 方案实现
在代码中,主要有两个容器:
- music_dict_list:按类似格式[{“name”: “真的爱你”, “score”: 9.5}]存储的歌曲列表
- music_score_nom_list:通过计算单手歌曲评分除以总评分归一化后的歌曲概率list
选歌曲的时候用以下代码就能得到和歌曲评分成正比挑选得到的歌曲名称。
np.random.choice(music_dict_list, p=music_score_nom_list)["music_name"]
0x05 测试
循环100万次,用dict
分别记录真的爱你
和再见理想
被选中的次数,最后相除得到比值,并保留两位小数且四舍五入,验证比值是否为约等于1.03.
0x06 完整代码
以下是作者自己写的一份简单代码,仅供参考:
import numpy as np
import pandas as pd
from decimal import Decimal
# 1.读取音乐列表
music_info = pd.read_table('musics.txt')
# 2.按格式[{"name": "真的爱你", "score": 9.5}]转换为列表
music_dict_list = music_info.to_dict(orient='records')
# 3.得到评分数组
music_score_array = np.array(music_info.to_dict(orient='list')["score"])
# 4.将得分表归一化
music_score_nom_list = (music_score_array / music_score_array.sum()).tolist()
# 5.代码测试
song_cnt_dict = {'真的爱你':0, '再见理想':0}
for i in range(1000000):
# 按评分来选歌曲
song = np.random.choice(music_dict_list, p=music_score_nom_list)["music_name"]
if song in song_cnt_dict.keys():
song_cnt_dict[song] += 1
# 循环100万次选歌,真的爱你被选中次数/再见理想被选中次数约为 1.03(保留两位小数且四舍五入)
print(float(Decimal(song_cnt_dict['真的爱你']/song_cnt_dict['再见理想']).quantize(Decimal('0.00'))))
0x07 总结
主要就是采用了概率归一化的思想。
代码里用了:
np.random.choice(music_dict_list, p=music_score_nom_list)
这个函数可以根据概率list来挑选目标list中元素,值得大家学习使用。