我想在JavaScript中洗牌一系列元素,如下所示:

[0, 3, 3] -> [3, 0, 3]
[9, 3, 6, 0, 6] -> [0, 3, 6, 9, 6]
[3, 3, 6, 0, 6] -> [0, 3, 6, 3, 6]

推荐答案

使用the modern version of the Fisher–Yates shuffle algorithm:

/**
 * Shuffles array in place.
 * @param {Array} a items An array containing the items.
 */
function shuffle(a) {
    var j, x, i;
    for (i = a.length - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i + 1));
        x = a[i];
        a[i] = a[j];
        a[j] = x;
    }
    return a;
}

ES2015(ES6)版本

/**
 * Shuffles array in place. ES6 version
 * @param {Array} a items An array containing the items.
 */
function shuffle(a) {
    for (let i = a.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [a[i], a[j]] = [a[j], a[i]];
    }
    return a;
}

但是,请注意,从2017年10月起,将变量与destructuring assignment互换会导致显著的性能损失.

使用

var myArray = ['1','2','3','4','5','6','7','8','9'];
shuffle(myArray);

实现原型

使用Object.defineProperty(method taken from this SO answer),我们还可以将此函数作为数组的原型方法来实现,而无需在for (i in arr)之类的循环中显示.下面将允许您拨打arr.shuffle()来洗牌数组arr:

Object.defineProperty(Array.prototype, 'shuffle', {
    value: function() {
        for (let i = this.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [this[i], this[j]] = [this[j], this[i]];
        }
        return this;
    }
});

Javascript相关问答推荐

JS、C++和C#给出不同的Base 64 Guid编码结果

Next.js Next/Image图像隐含性有任何类型-如何修复?

如何使用侧边滚动按钮具体滚动每4个格?

字节数组通过echo框架传输到JS blob

如何将连续的十六进制字符串拆分为以空间分隔的十六进制块,每个十六进制块包含32个二元组?

jQuery提交按钮重新加载页面,即使在WordPress中使用preventDefault()

Spring boot JSON解析错误:意外字符错误

当运行d3示例代码时,没有显示任何内容

Angular 中的类型错误上不存在获取属性

为什么123[';toString';].long返回1?

查询参数未在我的Next.js应用路由接口中定义

如何使本地html页面在重新加载时保持当前可隐藏部分的打开状态?

在查看网页时,如何使HTML中的按钮工作方式类似于鼠标上的滚轮或箭头键?

在JS/TS中将复杂图形转换为数组或其他数据 struct

如何组合Multer上传?

使用可配置项目创建网格

按特定顺序将4个数组组合在一起,按ID分组

在单击按钮时生成多个表单时的处理状态

如何设置时间选取器的起始值,仅当它获得焦点时?

REACT-本机错误:错误类型错误:无法读取未定义的容器的属性