最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS小知識點之打亂數(shù)組(洗牌)的3種常用方法

 更新時間:2026年02月04日 11:04:15   作者:WeiyuRAN.  
在JavaScript中,打亂數(shù)組順序是一項常見的操作,特別是在游戲開發(fā)、數(shù)據(jù)模擬或者測試場景中,這篇文章主要介紹了JS小知識點之打亂數(shù)組(洗牌)的3種常用方法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下

前言

在 JavaScript 開發(fā)中,數(shù)組打亂(又稱「洗牌」)是一個高頻需求,比如游戲中的隨機道具排列、抽獎活動的獎品順序、展示列表的隨機刷新等。今天我們就來拆解數(shù)組打亂的 3 種常用方法,從簡潔易用到嚴謹高效,幫你根據(jù)場景選擇最合適的方案。

一、完全隨機版(sort(() => Math.random() - 0.5))

這是最簡潔的數(shù)組打亂方法,一行代碼即可實現(xiàn),也是前端新手最容易上手的方案。

1.實現(xiàn)代碼

const animalList = ['??', '??', '??', '??', '??'];
// 數(shù)組打亂核心代碼 
const shuffledArr = animalList.sort(() => Math.random() - 0.5);
console.log(shuffledArr); // 每次輸出結(jié)果不同,如 ['??', '??', '??', '??', '??']

2.核心原理

  1. sort() 方法的
    sort() 是數(shù)組的排序方法,它接受一個比較函數(shù)作為參數(shù),排序結(jié)果完全由這個比較函數(shù)的返回值決定:
    返回 大于 0 的數(shù):交換兩個比較元素的位置;
    返回 小于 0 的數(shù):保持兩個比較元素的原有位置;
    返回 等于 0:不改變兩個元素的相對位置。
    這里的關(guān)鍵是:我們不需要基于元素本身的值排序,只需要通過隨機返回正數(shù) / 負數(shù),讓 sort() 隨機調(diào)整元素位置。

  2. Math.random() - 0.5 的隨機開關(guān)
    Math.random() 會返回一個 [0, 1) 區(qū)間內(nèi)的隨機小數(shù);
    用這個隨機小數(shù)減去 0.5,會得到一個 (-0.5, 0.5) 區(qū)間內(nèi)的隨機數(shù);
    結(jié)果為負數(shù)的概率約 50%(保持原位),結(jié)果為正數(shù)的概率約 50%(交換位置)。

兩者結(jié)合,sort() 會按照隨機決定兩個元素是否交換,經(jīng)過反復(fù)調(diào)整數(shù)組元素位置,最終實現(xiàn)數(shù)組完全隨機的打亂。

3. 優(yōu)缺點

  1. 優(yōu)點
    代碼極簡,一行實現(xiàn),無需額外封裝函數(shù);
    上手成本低,適合快速測試、短數(shù)組打亂等簡單場景;
    無額外依賴,兼容所有現(xiàn)代瀏覽器。
  2. 缺點
    不完全公平:由于 sort() 方法的底層排序算法(如 Chrome 采用快速排序),部分元素被打亂到任意位置的概率不均等,可能出現(xiàn)打亂不徹底的情況;
    性能一般:時間復(fù)雜度為 O(n log n),長數(shù)組場景下效率偏低。

4. 適用場景

適合普通業(yè)務(wù)場景,如短數(shù)組打亂、游戲中的隨機打亂、非核心業(yè)務(wù)的列表隨機展示等,無需追求絕對公平的場景。

二、嚴謹版打亂(Fisher-Yates 洗牌算法)

如果你的場景對公平性要求較高(如抽獎、棋牌游戲、金融相關(guān)的隨機排序),那么 Fisher-Yates 洗牌算法(又稱 Knuth 洗牌算法)是你的黃金選擇,它能保證每個元素被打亂到任意位置的概率完全均等,且性能更優(yōu)。

1. 實現(xiàn)代碼

/**
 * Fisher-Yates 洗牌算法(純函數(shù),不修改原數(shù)組)
 * @param {Array} arr - 待打亂的數(shù)組
 * @returns {Array} - 打亂后的新數(shù)組
 */
const fisherYatesShuffle = (arr) => {
    // 1. 復(fù)制原數(shù)組,避免修改原始數(shù)據(jù)(保證數(shù)據(jù)純凈)
    const copyArr = [...arr];
    // 2. 從數(shù)組最后一個元素開始,向前遍歷
    for (let i = copyArr.length - 1; i > 0; i--) {
        // 3. 生成 0 到 i 之間的隨機索引(包含 0 和 i)
        const randomIndex = Math.floor(Math.random() * (i + 1));
        // 4. 交換當前元素(i)和隨機索引元素(randomIndex)
        [copyArr[i], copyArr[randomIndex]] = [copyArr[randomIndex], copyArr[i]];
    }
    // 5. 返回打亂后的數(shù)組
    return copyArr;
};

// 測試使用
const animalList = ['??', '??', '??', '??', '??'];
const shuffledArr = fisherYatesShuffle(animalList);
console.log(shuffledArr); // 完全隨機的結(jié)果,且每個元素概率均等

2. 核心原理

Fisher-Yates 洗牌算法的核心思想是從后往前,隨機交換,步驟拆解如下:

  1. 先復(fù)制原數(shù)組,避免修改原始數(shù)據(jù)
  2. 從數(shù)組的最后一個元素開始向前遍歷,不處理第一個元素(索引 0),因為遍歷到最后時,它的位置自然確定
  3. 對于當前遍歷到的元素(索引 i),生成一個 [0, i] 區(qū)間內(nèi)的隨機索引 randomIndex,確保隨機范圍始終包含未被處理的元素
  4. 交換當前元素(copyArr[i])和隨機索引對應(yīng)的元素(copyArr[randomIndex]),讓當前元素隨機落入未被處理的位置
  5. 遍歷完成后,所有元素都已被隨機交換,得到完全打亂的數(shù)組。

3. 優(yōu)缺點分析

  1. 優(yōu)點
    完全公平:每個元素被交換到任意位置的概率均等,無打亂不徹底的問題,適合高要求場景;
    性能最優(yōu):時間復(fù)雜度為 O(n),僅遍歷數(shù)組一次,長數(shù)組場景下效率遠高于簡潔版方法;
    數(shù)據(jù)安全:純函數(shù)設(shè)計,不修改原數(shù)組,避免污染原始數(shù)據(jù)。
  2. 缺點
    代碼稍長,需要封裝函數(shù),比簡潔版多一點上手成本

4. 適用場景

適合對公平性和性能有要求的場景,如抽獎活動、棋牌游戲、長數(shù)組打亂、金融 / 電商等核心業(yè)務(wù)的隨機排序。

三、權(quán)重版打亂(Map 隨機映射)

如果想在簡潔性和公平性之間找一個平衡,還可以選擇權(quán)重版打亂,它通過給每個元素綁定固定隨機權(quán)重實現(xiàn)排序,比簡潔版更公平,代碼也相對精煉。

1. 實現(xiàn)代碼

/**
 * 權(quán)重版數(shù)組打亂
 * @param {Array} arr - 待打亂的數(shù)組
 * @returns {Array} - 打亂后的新數(shù)組
 */
const mapShuffle = (arr) => {
    // 1. 給每個元素綁定隨機權(quán)重,生成 [{ value: 元素, weight: 隨機數(shù) }] 格式數(shù)組
    const mappedArr = arr.map(item => ({
        value: item,
        weight: Math.random()
    }));
    // 2. 按隨機權(quán)重進行排序
    mappedArr.sort((a, b) => a.weight - b.weight);
    // 3. 提取原元素,返回打亂后的數(shù)組
    return mappedArr.map(item => item.value);
};

// 測試使用
const animalList = ['??', '??', '??', '??', '??'];
const shuffledArr = mapShuffle(animalList);
console.log(shuffledArr); // 公平性優(yōu)于簡潔版,代碼優(yōu)于 Fisher-Yates 算法

2. 核心原理

  1. 先通過 map() 方法遍歷原數(shù)組,給每個元素綁定一個唯一的隨機權(quán)重(Math.random() 生成);
  2. 按照權(quán)重對數(shù)組進行排序,權(quán)重小的元素排在前面,權(quán)重大的元素排在后面;
  3. 再通過 map() 方法提取綁定對象中的原元素,得到打亂后的數(shù)組。

這種方法的公平性優(yōu)于簡潔版,因為每個元素的權(quán)重是固定的,排序過程中不會出現(xiàn)「重復(fù)隨機」導(dǎo)致的概率不均。

3. 適用場景

適合普通業(yè)務(wù)場景中,既想追求一定公平性,又不想寫復(fù)雜的 Fisher-Yates 算法的場景,如展示列表的隨機刷新、簡單游戲的道具排列等。

總結(jié)

以上就是今天要講的內(nèi)容,本文僅僅簡單介紹了三種洗牌的方法。

tips

  1. 日常開發(fā)中,簡單場景優(yōu)先用 sort(() => Math.random() - 0.5),高效快捷;
  2. 核心業(yè)務(wù)(如抽獎)優(yōu)先用 Fisher-Yates 洗牌算法,保證公平與性能;
  3. 無論使用哪種方法,都建議復(fù)制原數(shù)組后再操作,避免污染原始數(shù)據(jù);
  4. 數(shù)組打亂的核心是「隨機調(diào)整元素位置」,不同方法的差異在于「隨機的公平性」和「執(zhí)行效率」。

到此這篇關(guān)于JS小知識點之打亂數(shù)組(洗牌)的3種常用方法的文章就介紹到這了,更多相關(guān)JS打亂數(shù)組方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

玉门市| 蕉岭县| 永顺县| 古蔺县| 桑植县| 新平| 承德市| 彭泽县| 南开区| 新乡县| 许昌县| 潜江市| 陵川县| 荆门市| 泰顺县| 周至县| 阜南县| 酒泉市| 东乌珠穆沁旗| 台东县| 奉化市| 龙门县| 甘肃省| 富顺县| 土默特左旗| 读书| 栖霞市| 白水县| 津南区| 拉孜县| 丰都县| 宜都市| 榆林市| 临西县| 海阳市| 瑞丽市| 巴林右旗| 崇州市| 喀什市| 华宁县| 镇巴县|