Генерация взвешенных случайных чисел в Javascript
У меня есть массив, который выглядит примерно так:
[
{
plays: 0,
otherData: someValues
}, {
plays: 4,
otherData: someValues
}, {
plays: 1,
otherData: someValues
}, {
plays: 2,
otherData: someValues
} {
plays: 9,
otherData: someValues
}, {
plays: 7,
otherData: someValues
}, {
plays: 5,
otherData: someValues
}, {
plays: 0,
otherData: someValues
}, {
plays: 8,
otherData: someValues
}
]
Это массив информации о песнях в плейлисте, гдеplays
это количество раз, когда песня была воспроизведена. Я & APOS; пытаясь придумать генератор взвешенных случайных чисел, который выберет индекс элемента, взвешенного таким образом, что менее проигранные песни будут с большей вероятностью выбраны. Вот код, который у меня сейчас есть:
function pickRandom(){
var oldIndex = index;
if(songs.length <= 1)
return index = 0;
var unheard = [];
for(i in songs){
if(!songs[i].plays)
unheard.push(i);
}if(unheard.length > 0)
return index = unheard[Math.round(Math.random() * (unheard.length - 1))];
var tries = 0;
while(index == oldIndex && tries < 100){
index = Math.round(Math.random() * (songs.length - 1));
tries++;
}return index;
}
В этом решении есть несколько вещей, которыми я недоволен. Во-первых, он не столько весит, сколько просто выбирает не сыгранную песню или любую старую случайную песню, если все в массиве было воспроизведено хотя бы один раз. Во-вторых, он создает новый массив, и поскольку списки воспроизведения иногда содержат сотни песен, от которых я бы хотел отказаться, если это возможно.
Наиболее близким решением, которое мне удалось найти, является многократное копирование каждого элемента в новый массив на основе егоplays
значение, затем выберите элемент из этого, но это ухудшает проблему создания нового массива, так как этот второй массив может легко достигать тысяч элементов. Я был бы очень признателен за любую помощь или предложения; даже псевдокод будет в порядке.