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 } ]
This is an array of information about the songs in the playlist, where plays is the number of times the song was played. I am trying to come up with a weighted random number generator that will select an index of an element weighted in such a way that less reproducible songs are more likely to be selected. Here is the code that 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 in this decision that I am unhappy with. Firstly, he is not weighed as much as he simply chooses an unplayable song or any old random one, if everything in the array was played at least once. Secondly, it creates a new array, and since there are sometimes hundreds of songs in playlists, I would like to brush it off as soon as possible.
The closest solution I could come up with is to copy each element to a new array several times based on its plays value, and then select an element from this, but this exacerbates the problem of creating a new array, since this second array can easily reach thousands of elements. I would be very grateful for any help or suggestions; even pseudo code will be fine.