Javascript中的加权随机数生成

编程入门 行业动态 更新时间:2024-10-27 20:30:43
本文介绍了Javascript中的加权随机数生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有一个看起来像这样的数组:

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.

推荐答案

我会做你想做的循环。总计列表中任何歌曲的最大播放次数,然后通过计算反向加权的数字并从反向总计中选择来反转概率。这样的事情:

I would do what you want to do with loops. Total up the max number of plays for any song in the list, then reverse the probability by calculating a number that is reverse weighted and choosing from the reverse total. Something like this:

function pickRandom(myArray) { var maxPlays = 0, reverseTotPlays = 0, ipl, picked, revAcc = 0; // Empty array or bad input param if (!myArray || !myArray.length) { return -1; } // Calculate the max plays for any song in the list for (ipl = 0; ipl < myArray.length; ++ipl) { if (myArray[ipl].plays > maxPlays) { maxPlays = myArray[ipl].plays; } } maxPlays += 1; // Avoid excluding max songs // Calculate the reverse weighted total plays for (ipl = 0; ipl < myArray.length; ++ipl) { reverseTotPlays += maxPlays - myArray[ipl].plays; } // Choose a random number over the reverse weighted spectrum picked = ~~(Math.random() * reverseTotPlays); // Find which array member the random number belongs to for (ipl = 0; ipl < myArray.length; ++ipl) { revAcc += maxPlays - myArray[ipl].plays; if (revAcc > picked) { return ipl; } } return myArray.length - 1; } var pp = [{ plays: 3 }, { plays: 1 }, { plays: 2 }]; console.log(pickRandom(pp));

工作JSFiddle 这里

Working JSFiddle Here

编辑:如果您不希望播放已播放的歌曲的概率为零在列表中播放了最多次,在第一次循环后为maxPlay添加+1。

Edit: If you don't want a zero probability on playing the songs that have been played the max times in the list, add +1 to maxPlays after the first loop.

更多推荐

Javascript中的加权随机数生成

本文发布于:2023-11-30 06:28:35,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1649021.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:随机数   Javascript

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!