从数组中挑选2个随机元素

从数组中选择2个唯一随机元素的最有效方法是什么(即,确保未选择相同的元素两次)。

我到目前为止:

var elem1; var elem2; elem1 = elemList[Math.ceil(Math.random() * elemList.length)]; do { elem2 = elemList[Math.ceil(Math.random() * elemList.length)]; } while(elem1 == elem2) 

但这通常会导致我的页面加载。

更好的解决方案?

额外的问题,我如何将其扩展到n元素

不要使用循环和比较。 代替

  • 洗牌arrays
  • 先拿两个要素

当列表只包含一个项目时,您的代码将挂起。 而不是使用== ,我建议使用=== ,在这种情况下看起来更合适。

另外,使用Math.floor而不是Math.ceillength属性等于 + 1

 var elem1; var elem2; var elemListLength = elemList.length; elem1 = elemList[Math.floor(Math.random() * elemListLength)]; if (elemListLength > 1) { do { elem2 = elemList[Math.floor(Math.random() * elemListLength)]; } while(elem1 == elem2); } 

http://underscorejs.org/#sample

_.sample(list,[n])

从列表中生成随机样本。 传递一个数字以从列表中返回n个随机元素。 否则将返回单个随机项。

 _.sample([1, 2, 3, 4, 5, 6]); => 4 _.sample([1, 2, 3, 4, 5, 6], 3); => [1, 6, 2] 

看看源它使用shuffle就像@ thg435建议的那样。

关于Rob W告诉你的内容,我将补充说,不同的解决方案是找到一个随机点,第二点找到一个随机偏移点:

 var elem1; var elem2; var elemListLength = elemList.length; var ix = Math.floor(Math.random() * elemListLength); elem1 = elemList[ix]; if (elemListLength > 1) { elem2 = elemList[(ix + 1 + Math.floor(Math.random() * (elemListLength - 1))) % elemListLength]; } 

我们加1是因为当前元素不能重新选择并减1,因为已经选择了一个元素。

例如,三个元素(0,1,2)的数组。 我们随机选择元素1.现在“好”偏移值为0和1,偏移量0给出元素2,偏移量1给出元素0。

请注意,这将为您提供两个具有不同INDEX的随机元素,而不是具有不同的VALUE!

如果你想获得n随机元素,你可以创建一个混乱的列表版本,然后返回混洗数组的前n元素。

如果您将数组洗牌并拼接要返回的元素数量,则返回值将包含尽可能多的项目,如果您要求的项目数多于数组中的项目数。 您可以使用slice()对实际数组或副本进行随机播放。

 Array.prototype.getRandom= function(num, cut){ var A= cut? this:this.slice(0); A.sort(function(){ return .5-Math.random(); }); return A.splice(0, num); } var a1= [1, 2, 3, 4, 5]; a1.getRandom(2) >>[4, 2] 

如果要从原始数组中删除所选项,以便第二次调用不包括第一次调用返回的元素,则传递第二个参数:getRandom(3,true);

 window.Memry=window.Memry || {}; Memry.a1= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; Memry.a1.getRandom(3,true); >>[5,10,7] Memry.a1.getRandom(3,true); >>[3,9,6] Memry.a1.getRandom(3,true); >>[8,4,1] Memry.a1.getRandom(3,true); >>[2] 

它可以使用内置function( 切片和排序 )来完成,

 var n = 2 randomItems = array.sort(() => .5 - Math.random()).slice(0, n);