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

JS數(shù)據(jù)去重的7種實(shí)用方法總結(jié)(附完整代碼與原理)

 更新時(shí)間:2025年11月17日 09:16:17   作者:前端開發(fā)小透明  
在JavaScript中數(shù)據(jù)去重是一個(gè)常見的操作,特別是在處理數(shù)組時(shí),這篇文章主要介紹了JS數(shù)據(jù)去重的7種實(shí)用方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在 JavaScript 開發(fā)中,“數(shù)據(jù)去重” 是高頻需求 —— 比如處理接口返回的重復(fù)列表、用戶輸入的重復(fù)值等。不同場(chǎng)景下,適合的去重方法不同,有的追求簡潔,有的追求性能,有的需要兼容復(fù)雜數(shù)據(jù)類型。今天就整理 7 種常用的去重方法,每種都附帶代碼和核心原理,幫你輕松應(yīng)對(duì)各種去重場(chǎng)景。

一、基礎(chǔ)方法:利用 Set 去重(最簡潔)

核心原理:ES6 新增的 Set 集合本身具有 “值唯一” 的特性,能自動(dòng)忽略重復(fù)值,再通過擴(kuò)展運(yùn)算符(...)或 Array.from() 轉(zhuǎn)回?cái)?shù)組即可。

代碼實(shí)現(xiàn)

// 待去重?cái)?shù)組(包含數(shù)字、字符串、重復(fù)值)
const arr = [1, 2, 2, "3", "3", 4, 4, 5];
// 方法 1:擴(kuò)展運(yùn)算符轉(zhuǎn)數(shù)組
const uniqueArr1 = [...new Set(arr)];
// 方法 2:Array.from() 轉(zhuǎn)數(shù)組(兼容不支持?jǐn)U展運(yùn)算符的環(huán)境)
const uniqueArr2 = Array.from(new Set(arr));
console.log(uniqueArr1); // 輸出:[1, 2, "3", 4, 5]
console.log(uniqueArr2); // 輸出:[1, 2, "3", 4, 5]

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):代碼最簡潔,一行搞定;性能優(yōu)秀(底層是哈希表實(shí)現(xiàn),時(shí)間復(fù)雜度 O (n));

  • 缺點(diǎn):無法區(qū)分 “值相同但類型不同” 的數(shù)據(jù)(比如 1"1" 會(huì)被視為不同值,這其實(shí)是合理的,若需強(qiáng)制相同需額外處理);不支持對(duì)象 / 數(shù)組等引用類型的去重(引用不同會(huì)被視為不同值)。

適用場(chǎng)景

處理簡單數(shù)據(jù)類型(數(shù)字、字符串、布爾值)的數(shù)組,追求代碼簡潔和性能。

二、傳統(tǒng)方法:利用 indexOf/includes 去重

核心原理:創(chuàng)建一個(gè)新數(shù)組,遍歷原數(shù)組,判斷當(dāng)前元素是否在新數(shù)組中(用 indexOfincludes),不在則加入新數(shù)組,最終得到去重后的數(shù)組。

代碼實(shí)現(xiàn)(indexOf 版)

const arr = [1, 2, 2, 3, 3, 3];
const uniqueArr = [];
for (let i = 0; i < arr.length; i++) {
 // indexOf 返回 -1 表示元素不在新數(shù)組中
 if (uniqueArr.indexOf(arr[i]) === -1) {
   uniqueArr.push(arr[i]);
 }
}
console.log(uniqueArr); // 輸出:[1, 2, 3]

代碼實(shí)現(xiàn)(includes 版,更直觀)

const arr = [1, 2, 2, 3, 3, 3];
const uniqueArr = [];
for (let item of arr) {
 // includes 直接返回布爾值,判斷元素是否存在
 if (!uniqueArr.includes(item)) {
   uniqueArr.push(item);
 }
}
console.log(uniqueArr); // 輸出:[1, 2, 3]

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):兼容性好(支持 ES5 及以上,無需擔(dān)心環(huán)境問題);邏輯直觀,容易理解;

  • 缺點(diǎn):性能較差(indexOf/includes 每次都會(huì)遍歷新數(shù)組,時(shí)間復(fù)雜度 O (n²),數(shù)據(jù)量大時(shí)會(huì)卡頓);同樣不支持引用類型去重。

適用場(chǎng)景

處理小規(guī)模的簡單類型數(shù)組,或需要兼容低版本瀏覽器的場(chǎng)景。

三、優(yōu)化性能:利用對(duì)象鍵名唯一性去重

核心原理:對(duì)象的鍵名(key)具有唯一性(不能重復(fù)),遍歷原數(shù)組時(shí),把元素作為對(duì)象的鍵名存儲(chǔ),同時(shí)判斷鍵名是否已存在,不存在則加入新數(shù)組。

代碼實(shí)現(xiàn)

const arr = [1, 2, 2, "2", 3, 3];
const uniqueArr = [];
const tempObj = {}; // 臨時(shí)對(duì)象,用于存儲(chǔ)已存在的元素
for (let item of arr) {
 // 把元素轉(zhuǎn)為字符串作為鍵名(避免 1 和 "1" 被視為不同鍵)
 const key = typeof item + item;
 if (!tempObj[key]) {
   tempObj[key] = true; // 標(biāo)記為已存在
   uniqueArr.push(item);
 }
}
console.log(uniqueArr); // 輸出:[1, 2, "2", 3]

關(guān)鍵細(xì)節(jié)

  • 為什么要加 typeof item?比如 1(數(shù)字)和 "1"(字符串),直接用 item 當(dāng)鍵名會(huì)都是 "1",導(dǎo)致誤判;加 typeof 后,鍵名會(huì)變成 "number1""string1",能正確區(qū)分。

  • 若想強(qiáng)制把 1"1" 視為相同值,可去掉 typeof,直接用 const key = item

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):性能優(yōu)秀(對(duì)象的鍵名查詢是哈希表操作,時(shí)間復(fù)雜度 O (n));支持區(qū)分 “值相同類型不同” 的場(chǎng)景;

  • 缺點(diǎn):需額外處理鍵名類型(避免誤判);不支持引用類型去重(對(duì)象作為鍵名會(huì)被轉(zhuǎn)為 [object Object],導(dǎo)致所有對(duì)象都被視為相同)。

適用場(chǎng)景

處理大規(guī)模的簡單類型數(shù)組,追求高性能,且需要區(qū)分值類型。

四、進(jìn)階方法:利用 filter + indexOf 去重

核心原理filter 方法會(huì)篩選出滿足條件的元素,結(jié)合 indexOf 判斷 “當(dāng)前元素在原數(shù)組中的第一次出現(xiàn)位置是否等于當(dāng)前索引”—— 如果等于,說明是第一次出現(xiàn),保留;否則是重復(fù)值,過濾掉。

代碼實(shí)現(xiàn)

const arr = [1, 2, 2, 3, 3, 4];
// filter 回調(diào)函數(shù):返回 true 則保留元素
const uniqueArr = arr.filter((item, index) => {
 // indexOf 會(huì)返回元素在數(shù)組中第一次出現(xiàn)的索引
 return arr.indexOf(item) === index;
});
console.log(uniqueArr); // 輸出:[1, 2, 3, 4]

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):代碼簡潔(一行搞定);邏輯優(yōu)雅,適合函數(shù)式編程風(fēng)格;

  • 缺點(diǎn):性能差(filter 遍歷一次,indexOf 每次又遍歷一次,時(shí)間復(fù)雜度 O (n²));不支持引用類型去重。

適用場(chǎng)景

處理小規(guī)模簡單類型數(shù)組,追求函數(shù)式編程風(fēng)格,不關(guān)心極致性能。

五、ES6 進(jìn)階:利用 Map 去重

核心原理Map 的鍵(key)可以是任意類型,且具有唯一性。遍歷原數(shù)組時(shí),用 Map.has() 判斷元素是否已存在,不存在則用 Map.set() 存儲(chǔ),并加入新數(shù)組。

代碼實(shí)現(xiàn)

const arr = [1, 2, 2, "3", "3", 4];
const uniqueArr = [];
const tempMap = new Map();
for (let item of arr) {
 if (!tempMap.has(item)) { // 判斷元素是否已在 Map 中
   tempMap.set(item, true); // 存儲(chǔ)元素(值隨便設(shè),只要有標(biāo)記即可)
   uniqueArr.push(item);
 }
}
console.log(uniqueArr); // 輸出:[1, 2, "3", 4]

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):性能優(yōu)秀(時(shí)間復(fù)雜度 O (n));支持更多鍵類型(比如 NaNSet 也支持,但 indexOf 不支持 NaN 的判斷);

  • 缺點(diǎn):代碼比 Set 稍繁瑣;不支持引用類型去重(引用不同會(huì)被視為不同鍵)。

適用場(chǎng)景

處理簡單類型數(shù)組,或需要存儲(chǔ) NaN 等特殊值的場(chǎng)景(indexOf 無法判斷 NaN,但 Map.has(NaN) 可以)。

六、復(fù)雜場(chǎng)景:引用類型(對(duì)象 / 數(shù)組)去重

前面的方法都無法處理對(duì)象 / 數(shù)組等引用類型(比如 { id: 1 }{ id: 1 } 會(huì)被視為不同值,因?yàn)橐貌煌?。此時(shí)需要通過 “比較內(nèi)容” 來實(shí)現(xiàn)去重,常用方法是 JSON.stringify 轉(zhuǎn)字符串手動(dòng)比較屬性。

方法 1:JSON.stringify 轉(zhuǎn)字符串(簡單對(duì)象適用)

核心原理:把對(duì)象轉(zhuǎn)為 JSON 字符串,再用 Set 或?qū)ο箧I名去重(字符串可以被唯一識(shí)別)。

// 待去重的對(duì)象數(shù)組(id 相同視為重復(fù))
const arr = [
 { id: 1, name: "小明" },
 { id: 1, name: "小明" }, // 重復(fù)
 { id: 2, name: "小紅" }
];
const uniqueArr = [...new Set(arr.map(item => JSON.stringify(item)))]
 .map(str => JSON.parse(str)); // 轉(zhuǎn)回對(duì)象
console.log(uniqueArr);
// 輸出:[{ id: 1, name: "小明" }, { id: 2, name: "小紅" }]

方法 2:手動(dòng)比較屬性(復(fù)雜對(duì)象適用)

核心原理:指定一個(gè)唯一標(biāo)識(shí)(比如 id),遍歷數(shù)組時(shí),判斷新數(shù)組中是否已有該標(biāo)識(shí)的對(duì)象,沒有則加入。

const arr = [
 { id: 1, name: "小明" },
 { id: 1, name: "小明" },
 { id: 2, name: "小紅" }
];
const uniqueArr = [];
for (let item of arr) {
 // 用 some 判斷新數(shù)組中是否已有相同 id 的對(duì)象
 const isRepeat = uniqueArr.some(uniqueItem => uniqueItem.id === item.id);
 if (!isRepeat) {
   uniqueArr.push(item);
 }
}
console.log(uniqueArr);
// 輸出:[{ id: 1, name: "小明" }, { id: 2, name: "小紅" }]

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):能處理引用類型的去重;

  • 缺點(diǎn)JSON.stringify 有局限性(比如無法處理 functionundefined、Symbol 等屬性);手動(dòng)比較屬性需指定唯一標(biāo)識(shí),靈活性較低。

適用場(chǎng)景

處理對(duì)象數(shù)組,且對(duì)象結(jié)構(gòu)簡單(無特殊屬性),或有明確唯一標(biāo)識(shí)(如 id)的場(chǎng)景。

七、排序后去重:利用 sort + 相鄰比較

核心原理:先通過 sort() 把數(shù)組排序(相同元素會(huì)相鄰),再遍歷排序后的數(shù)組,比較當(dāng)前元素和前一個(gè)元素,不同則加入新數(shù)組。

代碼實(shí)現(xiàn)

const arr = [3, 1, 2, 2, 3, 1, 4];
const uniqueArr = [];
// 先排序(注意:sort 默認(rèn)按字符串排序,數(shù)字需加比較函數(shù))
const sortedArr = arr.sort((a, b) => a - b); // 排序后:[1, 1, 2, 2, 3, 3, 4]
for (let i = 0; i < sortedArr.length; i++) {
 // 比較當(dāng)前元素和前一個(gè)元素,不同則保留
 if (sortedArr[i] !== sortedArr[i - 1]) {
   uniqueArr.push(sortedArr[i]);
 }
}
console.log(uniqueArr); // 輸出:[1, 2, 3, 4]

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):邏輯簡單,適合已排序或可排序的數(shù)組;

  • 缺點(diǎn):會(huì)改變?cè)瓟?shù)組的順序(若需保留原順序則不適用);性能受排序影響(sort 時(shí)間復(fù)雜度約 O (n log n));不支持引用類型去重。

適用場(chǎng)景

處理數(shù)字?jǐn)?shù)組,且不關(guān)心原數(shù)組順序的場(chǎng)景。

總結(jié):不同場(chǎng)景如何選?

場(chǎng)景需求推薦方法時(shí)間復(fù)雜度
簡單類型 + 代碼簡潔Set 去重O(n)
簡單類型 + 高性能 + 大規(guī)模對(duì)象鍵名去重 / Map 去重O(n)
低版本瀏覽器兼容indexOf/includes 去重O(n²)
函數(shù)式編程風(fēng)格filter + indexOf 去重O(n²)
對(duì)象數(shù)組(有唯一標(biāo)識(shí))手動(dòng)比較屬性去重O(n²)
數(shù)字?jǐn)?shù)組(不關(guān)心順序)sort + 相鄰比較去重O(n log n)

記住:沒有 “最好” 的去重方法,只有 “最適合” 的 —— 根據(jù)數(shù)據(jù)類型、數(shù)據(jù)規(guī)模和環(huán)境需求選擇即可!

到此這篇關(guān)于JS數(shù)據(jù)去重的7種實(shí)用方法總結(jié)的文章就介紹到這了,更多相關(guān)JS數(shù)據(jù)去重方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 微信小程序開發(fā)中生命周期的詳細(xì)介紹

    微信小程序開發(fā)中生命周期的詳細(xì)介紹

    生命周期是指一個(gè)對(duì)象從創(chuàng)建→>運(yùn)行>銷毀的整個(gè)階段,強(qiáng)調(diào)的是一個(gè)時(shí)間段,文中介紹了小程序中組件的生命周期,需要的朋友可以參考下
    2023-03-03
  • JS更改select內(nèi)option屬性的方法

    JS更改select內(nèi)option屬性的方法

    這篇文章主要介紹了JS更改select內(nèi)option屬性的方法,涉及JavaScript動(dòng)態(tài)操作頁面select元素屬性的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • js a標(biāo)簽點(diǎn)擊事件

    js a標(biāo)簽點(diǎn)擊事件

    本文將詳細(xì)介紹a標(biāo)簽上的點(diǎn)擊事件的相關(guān)知識(shí)。具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-03-03
  • Javascript oop設(shè)計(jì)模式 面向?qū)ο缶幊毯唵螌?shí)例介紹

    Javascript oop設(shè)計(jì)模式 面向?qū)ο缶幊毯唵螌?shí)例介紹

    這篇文章主要介紹了Javascript oop設(shè)計(jì)模式 面向?qū)ο缶幊毯唵螌?shí)例介紹的相關(guān)資料,這里附有實(shí)例代碼幫助大家學(xué)習(xí)理解,需要的朋友可以參考下
    2016-12-12
  • Javascript取整函數(shù)及向零取整幾種常用的方法

    Javascript取整函數(shù)及向零取整幾種常用的方法

    這篇文章主要介紹了Javascript取整函數(shù)及向零取整幾種常用的方法,每種方法都有其特點(diǎn)和適用場(chǎng)景,推薦使用Math.trunc(),因?yàn)樗Z義明確、代碼易讀且性能較好,需要的朋友可以參考下
    2025-01-01
  • javascript實(shí)現(xiàn)固定側(cè)邊欄

    javascript實(shí)現(xiàn)固定側(cè)邊欄

    這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)固定側(cè)邊欄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-02-02
  • 一文帶你徹底搞懂JS大文件分片上傳的實(shí)現(xiàn)

    一文帶你徹底搞懂JS大文件分片上傳的實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了前端JavaScript是如何實(shí)現(xiàn)大文件分片上傳的,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,需要的可以參考一下
    2023-05-05
  • BootStrap 動(dòng)態(tài)添加驗(yàn)證項(xiàng)和取消驗(yàn)證項(xiàng)的實(shí)現(xiàn)方法

    BootStrap 動(dòng)態(tài)添加驗(yàn)證項(xiàng)和取消驗(yàn)證項(xiàng)的實(shí)現(xiàn)方法

    這篇文章主要介紹了BootStrap 動(dòng)態(tài)添加驗(yàn)證項(xiàng)和取消驗(yàn)證項(xiàng)的實(shí)現(xiàn)方法的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • JavaScript判斷是否手機(jī)瀏覽器的五種方法

    JavaScript判斷是否手機(jī)瀏覽器的五種方法

    現(xiàn)在手機(jī)網(wǎng)站已經(jīng)很普及了,有時(shí)候前端網(wǎng)頁需要判斷,用戶使用的是手機(jī)瀏覽器還是電腦瀏覽器。這篇文章整理了JavaScript判斷是否手機(jī)瀏覽器的五種方法,通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值
    2022-11-11
  • 工作中常用到的ES6語法

    工作中常用到的ES6語法

    ECMAScript 6是JavaScript語言的下一代標(biāo)準(zhǔn),已經(jīng)在2015年6月正式發(fā)布了。這篇文章主要介紹了工作中常用到的ES6語法,需要的朋友可以參考下
    2018-09-09

最新評(píng)論

自贡市| 尉犁县| 上蔡县| 康保县| 九龙城区| 澜沧| 大石桥市| 库伦旗| 贡嘎县| 芒康县| 岚皋县| 濉溪县| 密山市| 德格县| 连州市| 青浦区| 屏东市| 南充市| 宣城市| 青铜峡市| 化隆| 衡山县| 阿城市| 定日县| 永吉县| 长顺县| 北安市| 广南县| 绥棱县| 重庆市| 金门县| 镇雄县| 宽城| 濉溪县| 宁明县| 隆尧县| 德钦县| 秦皇岛市| 屏东市| 左权县| 常州市|