I have an array that looks something like this:
[
{
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
}
]
It's an array of information about songs in a playlist, where plays
is the number of times a song has been played. I' trying to come up with a weighted random number generator that will pick an index of an element, weighted such that less-played songs are more likely to be picked. Here's the code I have now:
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;
}
There are a number of things with this solution that I'm unhappy with. First off, it's not weighted so much as it really just picks an unplayed song, or any old random one if everything in the array has been played at least once. Second, it creates a new array, and since playlists will sometimes have hundreds of songs, that's something I'd like to steer away from if possible.
The closest solution I've been able to come up with is copying each element into a new array multiple times based on its plays
value, then pick an element out of that, but that worsens the issue of creating a new array, since that second array could easily reach thousands of elements. I'd be much appreciative of any help or suggestions; even pseudocode would be fine.