高级前端
js
【Q447】如何实现一个数组洗牌函数 shuffle

如何实现一个数组洗牌函数 shuffle

更多描述 参考链接:https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle (opens in a new tab)

// 打乱数组,有可能是 [1, 3, 2, 4],但对原数组没有影响
shuffle([1, 2, 3, 4]);

Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 455 (opens in a new tab)

Author 回答者: shfshanyue (opens in a new tab)

先来一个利用 Array.prototype.sort 的技巧解法

const shuffle = (list) => list.sort((x, y) => Math.random() - 0.5);

使用以下算法可实现洗牌算法:

  1. 第 N 项数字与前 N 项数字随机选一相互交换
  2. 第 N-1 项数字与前 N-1 项数字随机选一相互交换
  3. ...
  4. 第 2 项数字与前 2 项数字随机选一相互交换

代码调试及测试可见 【Q447】如何实现一个数组洗牌函数 shuffle - codepen (opens in a new tab)

function shuffle(list) {
  const len = list.length;
  let result = [...list];
  for (let i = len - 1; i > 0; i--) {
    const swapIndex = Math.floor(Math.random() * (i + 1));
    [result[i], result[swapIndex]] = [result[swapIndex], result[i]];
  }
  return result;
}

Author 回答者: haotie1990 (opens in a new tab)

function shuffle(array) {
  let len = array.length;
  let _array = [...array];
  while (len) {
    let index = Math.floor(Math.random() * len--);
    [_array[index], _array[len]] = [_array[len], _array[index]];
  }
  return _array;
}

Author 回答者: Vi-jay (opens in a new tab)

function shuffle([...arr]) {
  const arrLen = arr.length;
  for (let i = 0; i < arrLen; i++) {
    const randomIdx = Math.floor(Math.random() * arrLen);
    [arr[randomIdx], arr[i]] = [arr[i], arr[randomIdx]];
  }
  return arr;
}
 
function shuffle([...arr]) {
  return arr.sort(() => Math.random() - 0.5);
}