【发布时间】:2011-11-10 16:22:29
【问题描述】:
如何以最有效的方式对数组的值进行洗牌?
每个元素只是一个包含 HTML 的字符串。
【问题讨论】:
-
看看here。
标签: javascript arrays shuffle performance
如何以最有效的方式对数组的值进行洗牌?
每个元素只是一个包含 HTML 的字符串。
【问题讨论】:
标签: javascript arrays shuffle performance
让我发布我自己的答案只是为了鼓励您不要使用随机的sort() 方法,因为它会产生不是那么随机的输出。
正如所说,Fisher-Yates shuffle 是最适合该目的的efficient 算法,并且可以使用以下 ES6 代码轻松实现:
const src = [...'abcdefg'],
shuffle = arr => arr.reduceRight((r,_,__,s) =>
(r.push(s.splice(0|Math.random()*s.length,1)[0]), r),[])
console.log(JSON.stringify(shuffle(src)))
.as-console-wrapper {min-height:100%}
【讨论】:
这是我洗牌数组的解决方案:
function shuffle(array) {
var resultArray = new Array();
for(i=0;i<array.length;i++) {
var randomEle = Math.floor(Math.random()*array.length);
resultArray.push(array[randomEle]);
array.splice(randomEle,1);
}
resultArray = resultArray.concat(array);
return resultArray;
}
这是一个随机比赛,将我的方法与其他 2 个方法进行比较
你有几个选择。
首先,您可以使用愚蠢的排序器...
arr = arr.sort(function() {
return Math.random() - .5
});
这是快速而肮脏的,但通常被认为是不好的做法。
随机排序Array 的最佳方法是使用Fisher-Yates shuffle。
var newArr = [];
while (arr.length) {
var randomIndex = Math.floor(Math.random() * arr.length),
element = arr.splice(randomIndex, 1)
newArr.push(element[0]);
}
【讨论】:
"often considered bad practice" 的 jsfiddle 链接而不是 Fisher-Yates shuffle?
"Phishing Site Blocked Phishing is a fraudulent attempt to get you to provide personal information under false pretenses."
这是我使用的。它为每个元素提供一个随机数,按这些随机数对数组进行排序(移动实际值),然后再次删除随机数。它似乎是均匀分布的,但我还没有在数学上证明它。
arr = arr.map(function(v) {
return [v, Math.random()];
}).sort(function(a, b) {
return a[1] - b[1];
}).map(function(v) {
return v[0];
});
http://jsfiddle.net/XQRFt/ - 测试结果(可能很慢)
【讨论】:
Array 方法,排除了 IE