python - 从多个其他列表创建 n 项长播放列表列表

标签 python list numpy

我正在尝试使用其他三个列表(高、中和低)中的值创建一个列表。新列表应该根据 probability_array 进行评估,它应该从哪个列表中选择一个随机值。新列表应该类似于播放列表:在随机选择的值被选择两次(从高、中或低)之前,特定列表的所有其他值(高、中或低)必须在新生成的列表中。

任何想法,我如何才能实现这一点。到目前为止我的代码:

import numpy as np


array_length = 30

high = [(1, 2), 3, 4, 5, 6, (7, 8, 9)]
medium = [10, 11, (12, 13), 14]
low = [100, 101, 102, (103, 104)]

probability_array = np.random.choice(
    ['High', 'Medium', 'Low',],
    array_length,
    p=[4/7, 2/7, 1/7]
)
# i. e.
"""
['Low' 'High' 'High' 'High' 'High' 'High' 'Medium' 'Medium' 'High' 'Medium'
 'High' 'High' 'Medium' 'Medium' 'High' 'High' 'Medium' 'Medium' 'High'
 'High' 'High' 'High' 'High' 'Medium' 'Medium' 'High' 'High' 'High' 'Low'
 'High']
"""

# new list should look like:
"""
[102, (1, 2), 4, (7, 8, 9), 3, 6, 14, ...]
"""

谢谢

最佳答案

np.random.choice 有一个选项可以指定项目被选中的概率。您可以用它构建一个 high, medium, low 列表,并将其输入另一个循环以正确构建您的播放列表
- 根据 roganjosh 的建议,我还删除了同一项目背靠背出现的能力

import numpy as np
import random 
import collections 

playlist_length = 30

# key is the match strength (ie. high, medium, low)
matches = {
    'high' : {
        'items' : [(1, 2), 3, 4, 5, 6, (7, 8, 9)],
        'prob' : 4/7
    },
    'medium' : {
        'items' : [10, 11, (12, 13), 14],
        'prob' : 2/7
    },
    'low' : {
        'items' : [100, 101, 102, (103, 104)],
        'prob' : 1/7
    }
}

# create two lists:
# a is a list of match strengths 
# p is the desired probability of an item from that match strength occuring
a, p = zip(*[(match, matches[match]['prob']) for match in matches])

# build a list of match strengths, with our chosen size and probability
results = np.random.choice(a=a, p=p, size=playlist_length)

# build our playlist 
playlist = []
last_item = None
for match_strength in results:
    # count all the items currently in playlist (a bit inefficient, probably don't have to recreate the Counter obj everytime)
    count_playlist = collections.Counter(playlist)

    # filter items of the given match strength, leaving out those that are at the current max 
    items = matches[match_strength]['items']
    max_count = max([count_playlist[item] for item in items])
    filtered = list(filter(lambda item: count_playlist[item] < max_count, items))

    # if all items have the same count, reset the filtered list to be any item
    if not len(filtered):
        filtered = items

    # drop last item so that it does not repeat
    if last_item and last_item in filtered and len(filtered) > 1:
        filtered.remove(last_item)

    # add one from filtered items to playlist
    new_item = random.choice(filtered)
    playlist.append(new_item)
    last_item = new_item

print(collections.Counter(results))
print(playlist)

输出:

计数器显示不同的匹配强度出现在可接受的频率 Counter({'high': 19, 'medium': 10, 'low': 1})

播放列表是
[(1, 2), 14, 4, 5, 102, 3, (7, 8, 9), 6, (1, 2), 11, 10, (12, 13), 4, 3, 10, (12, 13), 5, 11, (7, 8, 9), 14, 6, 4, (7, 8, 9), 5, 10, (1, 2), 6, 3, 11, 4]

关于python - 从多个其他列表创建 n 项长播放列表列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44934917/

相关文章:

python - 获取整个站点 python

python - 二维数组的多键字典

python - 如何将数据列表映射到函数列表?

python - 来自时间序列数据框的 matplotlib

python - Mastermind 检查结果 python

python - 在 Numpy Python 中修改数组 block

python - 快速半正弦逼近(Python/Pandas)

python - Scipy 相当于 numpy where 对于稀疏矩阵

python - numpy 列表理解和 +=/-= 运算符

python - 使用 Python 使用 Headless Selenium 浏览器提取数据