Cli*_*ote 1138 javascript arrays shuffle
我有这样一个数组:
var arr1 = ["a", "b", "c", "d"];
Run Code Online (Sandbox Code Playgroud)
我如何随机化/随机播放?
Chr*_*heD 1398
事实上的无偏差洗牌算法是Fisher-Yates(aka Knuth)Shuffle.
请参阅https://github.com/coolaj86/knuth-shuffle
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = array[currentIndex];
array[currentIndex] = array[randomIndex];
array[randomIndex] = temporaryValue;
}
return array;
}
// Used like so
var arr = [2, 11, 37, 42];
arr = shuffle(arr);
console.log(arr);
Run Code Online (Sandbox Code Playgroud)
有关所用算法的更多信息.
Lau*_*lst 653
这是Durstenfeld shuffle的JavaScript实现,这是Fisher-Yates的计算机优化版本:
/**
* Randomize array element order in-place.
* Using Durstenfeld shuffle algorithm.
*/
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
Run Code Online (Sandbox Code Playgroud)
Fisher-Yates算法通过为每个原始数组元素选择一个随机元素,然后从下一个绘制中排除它来工作.就像从一副牌中随机挑选一样.
这种排除是以巧妙的方式完成的(由Durstenfeld发明供计算机使用),方法是将拾取的元素与当前元素交换,然后从剩余部分中挑选下一个随机元素.为了获得最佳的效率,循环向后运行,这样随便挑简化(它可以随时从0开始),而且因为没有其他的选择了它跳过最后一个元素.
该算法的运行时间为O(n).请注意,shuffle是就地完成的.因此,如果您不想修改原始数组,请首先复制它.slice(0)
.
新的ES6允许我们一次分配两个变量.当我们想要交换两个变量的值时,这尤其方便,因为我们可以在一行代码中完成.这是使用此功能的相同功能的缩写形式.
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
Run Code Online (Sandbox Code Playgroud)
dea*_*unk 125
[社区编辑:这个答案是不正确的; 看评论.它留在这里供将来参考,因为这个想法并不罕见.]
[1,2,3,4,5,6].sort(function() {
return .5 - Math.random();
});
Run Code Online (Sandbox Code Playgroud)
con*_*con 74
人们可以(或应该)将它用作Array的原型:
来自ChristopheD:
Array.prototype.shuffle = function() {
var i = this.length, j, temp;
if ( i == 0 ) return this;
while ( --i ) {
j = Math.floor( Math.random() * ( i + 1 ) );
temp = this[i];
this[i] = this[j];
this[j] = temp;
}
return this;
}
Run Code Online (Sandbox Code Playgroud)
小智 62
使用underscore.js库._.shuffle()
对于这种情况,该方法很好.以下是该方法的示例:
var _ = require("underscore");
var arr = [1,2,3,4,5,6];
// Testing _.shuffle
var testShuffle = function () {
var indexOne = 0;
var stObj = {
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5
};
for (var i = 0; i < 1000; i++) {
arr = _.shuffle(arr);
indexOne = _.indexOf(arr, 1);
stObj[indexOne] ++;
}
console.log(stObj);
};
testShuffle();
Run Code Online (Sandbox Code Playgroud)
sup*_*ary 56
您可以使用地图和排序轻松完成:
let unshuffled = ['hello', 'a', 't', 'q', 1, 2, 3, {cats: true}]
let shuffled = unshuffled
.map((a) => ({sort: Math.random(), value: a}))
.sort((a, b) => a.sort - b.sort)
.map((a) => a.value)
Run Code Online (Sandbox Code Playgroud)
您可以随机播放多态数组,并且排序与Math.random一样随机,这对于大多数用途来说已经足够了.
由于元素是针对每次迭代不重新生成的一致键进行排序的,并且每次比较都来自同一分布,因此Math.random分布中的任何非随机性都会被取消.
coc*_*cco 48
新!
更短且可能更快的Fisher-Yates shuffle算法
function fy(a,b,c,d){//array,placeholder,placeholder,placeholder
c=a.length;while(c)b=Math.random()*(--c+1)|0,d=a[c],a[c]=a[b],a[b]=d
}
Run Code Online (Sandbox Code Playgroud)
脚本大小(使用fy作为函数名称):90bytes
演示 http://jsfiddle.net/vvpoma8w/
*除了chrome之外,所有浏览器都可能更快.
如果你有问题,就问吧.
编辑
是的,它更快
表现: http ://jsperf.com/fyshuffle
使用最高投票功能.
编辑 有一个超出计算(不需要--c + 1),没有人注意到
更短(4字节)和更快(测试它!).
function fy(a,b,c,d){//array,placeholder,placeholder,placeholder
c=a.length;while(c)b=Math.random()*c--|0,d=a[c],a[c]=a[b],a[b]=d
}
Run Code Online (Sandbox Code Playgroud)
在其他地方缓存var rnd=Math.random
然后使用rnd()
也会略微增加大数组的性能.
http://jsfiddle.net/vvpoma8w/2/
可读版本(使用原始版本.这是较慢的,vars是无用的,如闭包&";",代码本身也更短...也许读这个如何'缩小'Javascript代码,顺便说一句你不能在上面的javascript minifiers中压缩以下代码.)
function fisherYates( array ){
var count = array.length,
randomnumber,
temp;
while( count ){
randomnumber = Math.random() * count-- | 0;
temp = array[count];
array[count] = array[randomnumber];
array[randomnumber] = temp
}
}
Run Code Online (Sandbox Code Playgroud)
Kri*_*ekk 41
对于小型数组来说,一种非常简单的方法就是:
const someArray = [1, 2, 3, 4, 5];
someArray.sort(() => Math.random() - 0.5);
Run Code Online (Sandbox Code Playgroud)
它可能效率不高,但对于小型阵列,这种方法效果很好.这是一个例子,你可以看到它是如何随机(或不是),以及它是否适合你的用例.
const resultsEl = document.querySelector('#results');
const buttonEl = document.querySelector('#trigger');
const generateArrayAndRandomize = () => {
const someArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
someArray.sort(() => Math.random() - 0.5);
return someArray;
};
const renderResultsToDom = (results, el) => {
el.innerHTML = results.join(' ');
};
buttonEl.addEventListener('click', () => renderResultsToDom(generateArrayAndRandomize(), resultsEl));
Run Code Online (Sandbox Code Playgroud)
<h1>Randomize!</h1>
<button id="trigger">Generate</button>
<p id="results">0 1 2 3 4 5 6 7 8 9</p>
Run Code Online (Sandbox Code Playgroud)
Ben*_*arp 32
使用ES6语法可以缩短一些答案.
function getShuffledArr (array){
for (var i = array.length - 1; i > 0; i--) {
var rand = Math.floor(Math.random() * (i + 1));
[array[i], array[rand]] = [array[rand], array[i]]
}
}
Run Code Online (Sandbox Code Playgroud)
我个人使用这个功能,因为它是纯粹的,相对简单,根据我在谷歌Chrome上的测试最有效(与其他纯版本相比).
const getShuffledArr = arr => {
const newArr = arr.slice()
for (let i = newArr.length - 1; i > 0; i--) {
const rand = Math.floor(Math.random() * (i + 1));
[newArr[i], newArr[rand]] = [newArr[rand], newArr[i]];
}
return newArr
};
Run Code Online (Sandbox Code Playgroud)
正如您在本页中所看到的,过去提供的解决方案不正确.因此,考虑到可靠性和性能,我编写了以下函数来测试任何纯(无副作用)数组随机化函数.我用它来测试这个答案中提出的所有选项.
function testShuffleArrayFun(getShuffledArrayFun){
const arr = [0,1,2,3,4,5,6,7,8,9]
var countArr = arr.map(el=>{
return arr.map(
el=> 0
)
}) // For each possible position in the shuffledArr and for
// each possible value, we'll create a counter.
const t0 = performance.now()
const n = 1000000
for (var i=0 ; i<n ; i++){
// We'll call getShuffledArrayFun n times.
// And for each iteration, we'll increment the counter.
var shuffledArr = getShuffledArrayFun(arr)
shuffledArr.forEach(
(value,key)=>{countArr[key][value]++}
)
}
const t1 = performance.now()
console.log(`Count Values in position`)
console.table(countArr)
const frequencyArr = countArr.map( positionArr => (
positionArr.map(
count => count/n
)
))
console.log("Frequency of value in position")
console.table(frequencyArr)
console.log(`total time: ${t1-t0}`)
}
Run Code Online (Sandbox Code Playgroud)
您可以使用以下任一方法.
const getShuffledArr = arr => {
if (arr.length === 1) {return arr};
const rand = Math.floor(Math.random() * arr.length);
return [arr[rand], ...getShuffledArr(arr.filter((_, i) => i != rand))];
};
Run Code Online (Sandbox Code Playgroud)
ES6纯,递归
function getShuffledArr (arr){
return [...arr].map( (_, i, arrCopy) => {
var rand = i + ( Math.floor( Math.random() * (arrCopy.length - i) ) );
[arrCopy[rand], arrCopy[i]] = [arrCopy[i], arrCopy[rand]]
return arrCopy[i]
})
}
Run Code Online (Sandbox Code Playgroud)
此版本的效率低于迭代纯版本.
ES6 Pure使用array.map
function getShuffledArr (arr){
return arr.reduce(
(newArr, _, i) => {
var rand = i + ( Math.floor( Math.random() * (newArr.length - i) ) );
[newArr[rand], newArr[i]] = [newArr[i], newArr[rand]]
return newArr
}, [...arr]
)
}
Run Code Online (Sandbox Code Playgroud)
此版本的效率略低于迭代纯版本.
ES6 Pure使用array.reduce
function getShuffledArr (array){
for (var i = array.length - 1; i > 0; i--) {
var rand = Math.floor(Math.random() * (i + 1));
[array[i], array[rand]] = [array[rand], array[i]]
}
}
Run Code Online (Sandbox Code Playgroud)
此版本的效率略低于迭代纯版本.
Raf*_*nig 27
警告!
不建议将此答案用于随机化大型数组、密码学或任何其他需要真正随机性的应用程序,因为它存在偏差且效率低下。元素位置只是半随机的,它们往往会更接近其原始位置。请参阅/sf/answers/1305511861/。
1 : -1
您可以通过以下方式任意决定是否返回Math.random
:
[1, 2, 3, 4].sort(() => (Math.random() > 0.5) ? 1 : -1)
Run Code Online (Sandbox Code Playgroud)
尝试运行以下示例:
[1, 2, 3, 4].sort(() => (Math.random() > 0.5) ? 1 : -1)
Run Code Online (Sandbox Code Playgroud)
hak*_*iko 25
//one line solution
shuffle = (array) => array.sort(() => Math.random() - 0.5);
//Demo
let arr = [1, 2, 3];
shuffle(arr);
alert(arr);
Run Code Online (Sandbox Code Playgroud)
https://javascript.info/task/shuffle
Math.random() - 0.5
是一个可能为正数或为负数的随机数,因此排序功能会随机对元素进行重新排序。
Kin*_*rog 23
添加到@Laurens Holsts回答.这是50%压缩.
function shuffleArray(d) {
for (var c = d.length - 1; c > 0; c--) {
var b = Math.floor(Math.random() * (c + 1));
var a = d[c];
d[c] = d[b];
d[b] = a;
}
return d
};
Run Code Online (Sandbox Code Playgroud)
Bru*_*oLM 16
使用ES2015,您可以使用这个:
Array.prototype.shuffle = function() {
let m = this.length, i;
while (m) {
i = (Math.random() * m--) >>> 0;
[this[m], this[i]] = [this[i], this[m]]
}
return this;
}
Run Code Online (Sandbox Code Playgroud)
用法:
[1, 2, 3, 4, 5, 6, 7].shuffle();
Run Code Online (Sandbox Code Playgroud)
Top*_*phe 15
var shuffle = function(array) {
temp = [];
originalLength = array.length;
for (var i = 0; i < originalLength; i++) {
temp.push(array.splice(Math.floor(Math.random()*array.length),1));
}
return temp;
};
Run Code Online (Sandbox Code Playgroud)
Dan*_*tin 15
我发现这个变体在"被作者删除"的答案中悬而未决.与已经有许多赞成票的其他答案不同,这是:
shuffled
名称而不是shuffle
)Array.prototype.shuffled = function() {
return this.map(function(n){ return [Math.random(), n] })
.sort().map(function(n){ return n[1] });
}
Run Code Online (Sandbox Code Playgroud)
Alj*_*aro 11
这是最简单的一个,
function shuffle(array) {
return array.sort(() => Math.random() - 0.5);
}
Run Code Online (Sandbox Code Playgroud)
进一步的例子,你可以在这里查看
Tín*_*ang 10
您可以通过以下方式轻松完成:
// array
var fruits = ["Banana", "Orange", "Apple", "Mango"];
// random
fruits.sort(function(a, b){return 0.5 - Math.random()});
// out
console.log(fruits);
Run Code Online (Sandbox Code Playgroud)
递归解决方案:
function shuffle(a,b){
return a.length==0?b:function(c){
return shuffle(a,(b||[]).concat(c));
}(a.splice(Math.floor(Math.random()*a.length),1));
};
Run Code Online (Sandbox Code Playgroud)
Fisher-Yates在javascript中随机播放.我在这里发布这个是因为使用两个实用函数(swap和randInt)来澄清算法与此处的其他答案相比较.
function swap(arr, i, j) {
// swaps two elements of an array in place
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
function randInt(max) {
// returns random integer between 0 and max-1 inclusive.
return Math.floor(Math.random()*max);
}
function shuffle(arr) {
// For each slot in the array (starting at the end),
// pick an element randomly from the unplaced elements and
// place it in the slot, exchanging places with the
// element in the slot.
for(var slot = arr.length - 1; slot > 0; slot--){
var element = randInt(slot+1);
swap(arr, element, slot);
}
}
Run Code Online (Sandbox Code Playgroud)
更新:这里我建议一个相对简单(不是从复杂性的角度来看)和短算法,它可以很好地处理小型数组,但是当你处理大型数组时,它肯定会比经典的Durstenfeld算法花费更多.你可以在这个问题的最热门回复中找到Durstenfeld.
原始答案:
如果您不希望您的shuffle函数改变源数组,您可以将其复制到局部变量,然后使用简单的混洗逻辑完成其余操作.
function shuffle(array) {
var result = [], source = array.concat([]);
while (source.length) {
let index = Math.floor(Math.random() * source.length);
result.push(source[index]);
source.splice(index, 1);
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
随机逻辑:拾取随机索引,然后将相应的元素添加到结果数组中,并将其从源数组副本中删除.重复此操作,直到源数组变空.
如果你真的想要它简短,这里有多远:
function shuffle(array) {
var result = [], source = array.concat([]);
while (source.length) {
let index = Math.floor(Math.random() * source.length);
result.push(source.splice(index, 1)[0]);
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
基准
让我们先看看结果,然后我们将看看shuffle
下面的每个实现-
拼接很慢
任何使用splice
或shift
在循环中的解决方案都会非常慢。当我们增加数组的大小时,这一点尤其明显。在一个朴素的算法中,我们 -
rand
位置i
,t
t[i]
到输出splice
i
数组中的位置t
为了夸大缓慢的效果,我们将在包含一百万个元素的数组上演示这一点。以下脚本将近 30 秒-
const shuffle = t =>
Array.from(sample(t, t.length))
function* sample(t, n)
{ let r = Array.from(t)
while (n > 0 && r.length)
{ const i = rand(r.length) // 1
yield r[i] // 2
r.splice(i, 1) // 3
n = n - 1
}
}
const rand = n =>
Math.floor(Math.random() * n)
function swap (t, i, j)
{ let q = t[i]
t[i] = t[j]
t[j] = q
return t
}
const size = 1e6
const bigarray = Array.from(Array(size), (_,i) => i)
console.time("shuffle via splice")
const result = shuffle(bigarray)
console.timeEnd("shuffle via splice")
document.body.textContent = JSON.stringify(result, null, 2)
Run Code Online (Sandbox Code Playgroud)
body::before {
content: "1 million elements via splice";
font-weight: bold;
display: block;
}
Run Code Online (Sandbox Code Playgroud)
流行很快
诀窍splice
不是使用超级高效的pop
. 要做到这一点,代替典型的splice
电话,你 -
i
t[i]
与最后一个元素交换,t[t.length - 1]
t.pop()
到结果中现在我们可以shuffle
在不到 100 毫秒的时间内处理一百万个元素——
const shuffle = t =>
Array.from(sample(t, t.length))
function* sample(t, n)
{ let r = Array.from(t)
while (n > 0 && r.length)
{ const i = rand(r.length) // 1
swap(r, i, r.length - 1) // 2
yield r.pop() // 3
n = n - 1
}
}
const rand = n =>
Math.floor(Math.random() * n)
function swap (t, i, j)
{ let q = t[i]
t[i] = t[j]
t[j] = q
return t
}
const size = 1e6
const bigarray = Array.from(Array(size), (_,i) => i)
console.time("shuffle via pop")
const result = shuffle(bigarray)
console.timeEnd("shuffle via pop")
document.body.textContent = JSON.stringify(result, null, 2)
Run Code Online (Sandbox Code Playgroud)
body::before {
content: "1 million elements via pop";
font-weight: bold;
display: block;
}
Run Code Online (Sandbox Code Playgroud)
甚至更快
shuffle
上面的两个实现产生了一个新的输出数组。输入数组未修改。这是我首选的工作方式,但是您可以通过原地改组来进一步提高速度。
shuffle
在不到 10 毫秒的时间内将低于100 万个元素-
function shuffle (t)
{ let last = t.length
let n
while (last > 0)
{ n = rand(last)
swap(t, n, --last)
}
}
const rand = n =>
Math.floor(Math.random() * n)
function swap (t, i, j)
{ let q = t[i]
t[i] = t[j]
t[j] = q
return t
}
const size = 1e6
const bigarray = Array.from(Array(size), (_,i) => i)
console.time("shuffle in place")
shuffle(bigarray)
console.timeEnd("shuffle in place")
document.body.textContent = JSON.stringify(bigarray, null, 2)
Run Code Online (Sandbox Code Playgroud)
body::before {
content: "1 million elements in place";
font-weight: bold;
display: block;
}
Run Code Online (Sandbox Code Playgroud)
首先,看看这里为在JavaScript不同的排序方法极大的视觉对比.
其次,如果您快速查看上面的链接,您会发现random order
与其他方法相比,排序似乎表现相对较好,同时实现起来非常简单快捷,如下所示:
function shuffle(array) {
var random = array.map(Math.random);
array.sort(function(a, b) {
return random[array.indexOf(a)] - random[array.indexOf(b)];
});
}
Run Code Online (Sandbox Code Playgroud)
编辑:正如@gregers所指出的,比较函数是用值而不是索引调用的,这就是你需要使用的原因indexOf
.请注意,此更改使得代码不太适合indexOf
在O(n)时间内运行的较大数组.
2019 年我们仍在改组数组,所以这是我的方法,对我来说似乎既简洁又快速:
const src = [...'abcdefg'];
const shuffle = arr =>
[...arr].reduceRight((res,_,__,s) =>
(res.push(s.splice(0|Math.random()*s.length,1)[0]), res),[]);
console.log(shuffle(src));
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper {min-height: 100%}
Run Code Online (Sandbox Code Playgroud)
使用Fisher-Yates shuffle 算法和 ES6:
// Original array
let array = ['a', 'b', 'c', 'd'];
// Create a copy of the original array to be randomized
let shuffle = [...array];
// Defining function returning random value from i to N
const getRandomValue = (i, N) => Math.floor(Math.random() * (N - i) + i);
// Shuffle a pair of two elements at random position j
shuffle.forEach( (elem, i, arr, j = getRandomValue(i, arr.length)) => [arr[i], arr[j]] = [arr[j], arr[i]] );
console.log(shuffle);
// ['d', 'a', 'b', 'c']
Run Code Online (Sandbox Code Playgroud)
小智 6
我发现这很有用:
const shuffle = (array: any[]) => {
return array.slice().sort(() => Math.random() - 0.5);
}
console.log(shuffle([1,2,3,4,5,6,7,8,9,10]));
// Output: [4, 3, 8, 10, 1, 7, 9, 2, 6, 5]
Run Code Online (Sandbox Code Playgroud)
Fisher-Yates的另一个实现,使用严格模式:
function shuffleArray(a) {
"use strict";
var i, t, j;
for (i = a.length - 1; i > 0; i -= 1) {
t = a[i];
j = Math.floor(Math.random() * (i + 1));
a[i] = a[j];
a[j] = t;
}
return a;
}
Run Code Online (Sandbox Code Playgroud)
随机化数组
var arr = ['apple','cat','Adam','123','Zorro','petunia'];
var n = arr.length; var tempArr = [];
for ( var i = 0; i < n-1; i++ ) {
// The following line removes one random element from arr
// and pushes it onto tempArr
tempArr.push(arr.splice(Math.floor(Math.random()*arr.length),1)[0]);
}
// Push the remaining item onto tempArr
tempArr.push(arr[0]);
arr=tempArr;
Run Code Online (Sandbox Code Playgroud)
对CoolAJ86 答案的简单修改,不会修改原始数组:
/**
* Returns a new array whose contents are a shuffled copy of the original array.
* @param {Array} The items to shuffle.
* /sf/answers/171568351/
* /sf/answers/3084992151/
*/
const shuffle = (array) => {
let currentIndex = array.length;
let temporaryValue;
let randomIndex;
const newArray = array.slice();
// While there remains elements to shuffle...
while (currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// Swap it with the current element.
temporaryValue = newArray[currentIndex];
newArray[currentIndex] = newArray[randomIndex];
newArray[randomIndex] = temporaryValue;
}
return newArray;
};
Run Code Online (Sandbox Code Playgroud)
只是为了指责派。在这里,我提出了Fisher Yates shuffle的递归实现(我认为)。它给出统一的随机性。
注意:(~~
双波浪号运算符)实际上的行为类似于Math.floor()
正实数。只是一个捷径。
var shuffle = a => a.length ? a.splice(~~(Math.random()*a.length),1).concat(shuffle(a))
: a;
console.log(JSON.stringify(shuffle([0,1,2,3,4,5,6,7,8,9])));
Run Code Online (Sandbox Code Playgroud)
编辑:上面的代码是O(n ^ 2)的使用,.splice()
但是我们可以通过交换技巧消除O(n)中的拼接和混洗。
var shuffle = (a, l = a.length, r = ~~(Math.random()*l)) => l ? ([a[r],a[l-1]] = [a[l-1],a[r]], shuffle(a, l-1))
: a;
var arr = Array.from({length:3000}, (_,i) => i);
console.time("shuffle");
shuffle(arr);
console.timeEnd("shuffle");
Run Code Online (Sandbox Code Playgroud)
问题是,JS无法应对大型递归。在这种情况下,根据您的浏览器引擎和一些未知事实,您将数组大小限制在3000〜7000之间。
所有其他答案都基于Math.random(),它很快但不适用于密码级随机化.
在下面的代码是使用公知的Fisher-Yates
,同时利用算法Web Cryptography API
对随机化的加密级.
var d = [1,2,3,4,5,6,7,8,9,10];
function shuffle(a) {
var x, t, r = new Uint32Array(1);
for (var i = 0, c = a.length - 1, m = a.length; i < c; i++, m--) {
crypto.getRandomValues(r);
x = Math.floor(r / 65536 / 65536 * m) + i;
t = a [i], a [i] = a [x], a [x] = t;
}
return a;
}
console.log(shuffle(d));
Run Code Online (Sandbox Code Playgroud)
使用ES6功能的现代短内联解决方案:
['a','b','c','d'].map(x => [Math.random(), x]).sort(([a], [b]) => a - b).map(([_, x]) => x);
Run Code Online (Sandbox Code Playgroud)
(出于教育目的)
尽管已经建议了许多实现,但是我觉得我们可以使用forEach循环使它更短,更容易,因此我们不必担心计算数组长度,并且可以安全地避免使用临时变量。
var myArr = ["a", "b", "c", "d"];
myArr.forEach((val, key) => {
randomIndex = Math.ceil(Math.random()*(key + 1));
myArr[key] = myArr[randomIndex];
myArr[randomIndex] = val;
});
// see the values
console.log('Shuffled Array: ', myArr)
Run Code Online (Sandbox Code Playgroud)
我使用这两种方法:
该方法不会修改原数组
shuffle(array);
Run Code Online (Sandbox Code Playgroud)
shuffle(array);
Run Code Online (Sandbox Code Playgroud)
该方法修改原数组
array.shuffle();
Run Code Online (Sandbox Code Playgroud)
function shuffle(arr) {
var len = arr.length;
var d = len;
var array = [];
var k, i;
for (i = 0; i < d; i++) {
k = Math.floor(Math.random() * len);
array.push(arr[k]);
arr.splice(k, 1);
len = arr.length;
}
for (i = 0; i < d; i++) {
arr[i] = array[i];
}
return arr;
}
var arr = ["a", "b", "c", "d"];
arr = shuffle(arr);
console.log(arr);
Run Code Online (Sandbox Code Playgroud)
您可以使用lodash
随机播放。奇迹般有效
import _ from lodash;
let numeric_array = [2, 4, 6, 9, 10];
let string_array = ['Car', 'Bus', 'Truck', 'Motorcycle', 'Bicycle', 'Person']
let shuffled_num_array = _.shuffle(numeric_array);
let shuffled_string_array = _.shuffle(string_array);
console.log(shuffled_num_array, shuffled_string_array)
Run Code Online (Sandbox Code Playgroud)
其工作原理是从未洗牌的数组的副本中随机删除项目,直到没有剩余的为止。它使用新的 ES6生成器函数。
只要 Math.random() 是公平的,这将是一个完全公平的洗牌。
let arr = [1,2,3,4,5,6,7]
function* shuffle(arr) {
arr = [...arr];
while(arr.length) yield arr.splice(Math.random()*arr.length|0, 1)[0]
}
console.log([...shuffle(arr)])
Run Code Online (Sandbox Code Playgroud)
或者,使用 ES6 和 splice:
let arr = [1,2,3,4,5,6,7]
let shuffled = arr.reduce(([a,b])=>
(b.push(...a.splice(Math.random()*a.length|0, 1)), [a,b]),[[...arr],[]])[1]
console.log(shuffled)
Run Code Online (Sandbox Code Playgroud)
或者,ES6索引交换方法:
let arr = [1,2,3,4,5,6,7]
let shuffled = arr.reduce((a,c,i,r,j)=>
(j=Math.random()*(a.length-i)|0,[a[i],a[j]]=[a[j],a[i]],a),[...arr])
console.log(shuffled)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
665732 次 |
最近记录: |