在一个数组中随机排列元素?

8
我为我的艺术家朋友创建了一个网站,她希望布局保持不变,但也想把新的绘画作品混合到当前的布局中。因此,我在主画廊页面上有12个缩略图(thumb1 - thumb12)和18个图像(img1 - img18)需要放置。
我想到的方法是创建一个包含所有图像的数组,并将其随机化,然后简单地刮掉前12个并加载到缩略图插槽中。另一种方法是从数组中随机选择12个图像。在第一种情况下,我找不到随机化数组元素的方法。在后一种情况下,我无法想象如何防止图像重复加载,除非使用第二个数组,这似乎非常低效且令人担忧。
顺便说一下,我正在使用Javascript完成所有这些工作。

可能是如何随机化JavaScript数组?的重复问题。 - Bergi
4个回答

18

我之前写过一个程序,碰巧能够满足你的需求。我认为ojblass所提到的是Fisher-Yates随机算法:

Array.prototype.shuffle = function() {
   var i = this.length;
   while (--i) {
      var j = Math.floor(Math.random() * (i + 1))
      var temp = this[i];
      this[i] = this[j];
      this[j] = temp;
   }

   return this; // for convenience, in case we want a reference to the array
};

请注意,修改 Array.prototype 可能被认为是不良行为。您可能希望将其实现为以数组作为参数的独立方法。不管怎样,完成以下操作:

var randomSubset = originalArray.shuffle().slice(0,13);

或者,如果你不想真正修改原始内容:

var randomSubset = originalArray.slice(0).shuffle().slice(0,13);

请注意,内循环是所提到的 Fisher-Yates 洗牌算法。而外循环则进行了多次洗牌。(这并没有什么问题)。 - Bill the Lizard
2
关于你的“iters”循环,需要注意一点。费舍尔-耶茨洗牌算法被认为是无偏的,这意味着每个排列都有相等的可能性。多次混合数组并不意味着“更好的混合”。 - Robert Cartaino
即使随机数分布高度不均匀,我也可以将那部分编辑掉,因为正如Bill指出的那样,它会混淆问题的答案。 - Jeremy Huiskamp
顺便提一下,第四行缺少一个分号。 - programking
在某些情况下,这个函数会导致内存泄漏,但大多数情况下它是有效的。 - iamawebgeek
@zazu,你能解释一下内存泄漏吗? - Jeremy Huiskamp

6

1

我见过的大多数排序函数都要求比较函数是一致的,如果不是,则结果未定义。我可以想象,如果随机结果不断重新排列它认为已经按正确顺序排列的项目,可能会使排序函数陷入无限循环(尽管在实践中可能不会发生)。 - Jeremy Huiskamp

1

你的第一种方法是可行的。只需将这18个元素随机排列,然后取前12个即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接