方法 #1
function Shuffle(o) {
for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
return o;
};
用法
var testArray = [1,2,3,4,5];
Shuffle(testArray);
// jQuery to dump out new values to element with ID of 'dump'
$(function() {
for (var i=0;i<testArray.length;i++) {
$("#dump").append(testArray[i]);
}
});
方法 #2
yourArray.sort(function() { return 0.5 - Math.random() });
不错..这段代码片段帮了我很大的忙!谢谢 :)
方法 #2
yourArray.sort(function() { return 0.5 – Math.random() });
这对我也非常有帮助,谢谢。
+1 为方法 #2 中的 .sort() 方法!非常巧妙…
嘿,再次非常有帮助,真的很高兴看到除了一个非常好的 CSS 资源外,CSS-tricks 也是一个很棒的 JS 资源!!
谢谢!!
嘿,
非常有用!谢谢!一个问题,你能解释一下方法 2 是如何工作的吗?
尤其是 { return 0.5 – Math.random() });。这是如何对数组进行排序的?
问候
我试着解释一下。
该 sort 函数 允许你传递一个比较函数,该函数的返回值决定了数组中对象的排序方式。
所以,如果它返回
-1
,则对象 A 的索引将低于 B。0
将保持它们的顺序不变,而1
将使 B 的索引低于 A。这是我从文档中了解到的。但这如何应用于提供的代码呢?
Math.random()
返回 0 到 1 之间的随机数。因此,在0.5 - Math.random()
中,你将得到 -1 到 1 之间的数字,这正是 sort 函数需要的。因此,数组中的每个对象都分配了一个随机索引号,然后按该索引排序。
我可能是错的,很可能是我错了,但这就是我理解的方式。我 100% 确定
0.5 - Math.Random
部分,但sort
函数是我不完全确定的部分。但嘿,它有效,对吧?
其工作原理如下
当这样的函数传递到 array.sort() 时,数组元素将根据每对元素“a”和“b”之间的关系以及函数的返回值进行排序。三个可能的返回值为:0(大于 0)
小于 0:“a”的索引应该低于“b”
零:“a”和“b”应被视为相等,并且不执行排序。
大于 0:“b”的索引应该低于“a”
当你执行 Math.random() 时,它会返回 0 到 1 之间的随机数。因此,在上述情况下,在 50% 的情况下,0.5 将小于 Math.random() 数,而在另一半情况下,它将大于。当它较小时,排序顺序为升序,当它较大时,排序顺序为降序。这导致数组的随机排序顺序。
不要使用 Array.sort() 方法!它不能执行随机洗牌。在第一种方法中实现的 Fisher-Yates 算法是最佳选择。下面的链接展示了此算法的更清晰的实现,并解释了为什么 Array.sort() 方法是错误的。
http://sroucheray.org/blog/2009/11/array-sort-should-not-be-used-to-shuffle-an-array/
你是个天才!!!!谢谢!
你是个天才!!!!谢谢!
http://eagle-design.ir/
感谢 Chris,我借用了你的 Shuffle 方法来制作这个纸牌游戏演示
http://codepen.io/bitmapshades/pen/raOZMa
圣诞快乐!
应该避免使用 sort 版本。你可以很容易地观察到它很少充分地洗牌最后的元素(它们通常保留在相同的位置)。
sort 不好的原因是 - sort 针对你的愿望(你提供的函数)进行了优化排序。你提供的函数实际上旨在接受两个参数(数组中的两个元素)。你应该在函数中比较它们,如果第一个应该在第二个之前排序则返回 -1,如果第二个应该在第一个之前排序则返回 1,如果它们相等则返回 0……)
因此,sort 是一种很棒的方法,因为你可以提供自己的逻辑来根据你提供的函数对数组进行排序。你可以控制你希望事物如何排序。
而 JavaScript 则控制你的函数被调用多少次以及使用数组中的哪些元素 - JS 引擎旨在尽可能少地调用它,只需足以确定正确的排序顺序即可。然后它停止调用 sort。这样,排序数组所需的时间最少。
但是,当你忽略比较元素并只返回随机数时,JS 引擎仍然试图最小化调用 - 因此,大多数随机 -1 和 1 值序列都会让它得出结论,即它已经完成了所有必要的排序,这远远早于所有元素都被洗牌。
所以:请使用 sort 以根据逻辑规则以有序的方式排序事物。但不要用它来洗牌数组!:D
可以在此处找到更理论的解释(和测量结果)
http://www.robweir.com/blog/2010/02/microsoft-random-browser-ballot.html
如果你正在寻找一些不会破坏原始数组但会提供洗牌副本的内容,你可以使用类似以下内容
Array.prototype.shuffle = function(){
var x = this.slice(), y = [];
while(x.length){y.push(x.splice(Math.floor(Math.random()*x.length),1)[0]);}
return y;
}
现在所有数组都可以像这样洗牌
var a = [1,2,3,4,6,7,8];
console.log( “Shuffle 1”, a.shuffle() );
console.log( “Shuffle 2”, b.shuffle() );
等等。
速度比较
https://jsperf.com/array-shuffe-test
方法 #2 不起作用!
http://codepen.io/GottZ/pen/ZbEaZg
从统计学上讲,交换在 sort 内部发生的次数仅为“需要”时的一半,因此你对原始值的偏差会很大。
如果我们将代码更改为:“yourArray.sort(function() { return Math.random() – Math.random() });”?这会消除偏差吗?
var arr = [1, 2, 3, 4];
function Shuffle(a){for(var b,c,d=a.length; d>0;)c=Math.floor(Math.random()*d),d–,b=a[d],a[d]=a[c],a[c]=b;return a;}
for(i=0;i<100;i++){
document.write(Shuffle(arr)+””);
}
这是一个字母数字字符的密码,每次运行代码时都会更改,就像 rot13 一样。我称之为 Rot-Rand。
第二种方法看起来非常优雅和巧妙。
我仍然担心如果 Web 浏览器使用 BubbleSort 或 QuickSort 实现排序算法会发生什么…
似乎对于某些排序算法来说没有问题,但对于其他算法,它可能会导致它们永远运行,因为它们几乎永远不会获得一系列“正确”的响应,因为其概率呈指数级趋近于 0。
太棒了!这救了我!非常感谢 :)