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

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

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

前言

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

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

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

代碼實現(xiàn)

// 待去重數(shù)組(包含數(shù)字、字符串、重復值)
const arr = [1, 2, 2, "3", "3", 4, 4, 5];
// 方法 1:擴展運算符轉(zhuǎn)數(shù)組
const uniqueArr1 = [...new Set(arr)];
// 方法 2:Array.from() 轉(zhuǎn)數(shù)組(兼容不支持擴展運算符的環(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)缺點

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

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

適用場景

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

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

核心原理:創(chuàng)建一個新數(shù)組,遍歷原數(shù)組,判斷當前元素是否在新數(shù)組中(用 indexOfincludes),不在則加入新數(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]

代碼實現(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)缺點

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

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

適用場景

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

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

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

代碼實現(xiàn)

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

關鍵細節(jié)

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

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

優(yōu)缺點

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

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

適用場景

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

四、進階方法:利用 filter + indexOf 去重

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

代碼實現(xiàn)

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

優(yōu)缺點

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

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

適用場景

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

五、ES6 進階:利用 Map 去重

核心原理Map 的鍵(key)可以是任意類型,且具有唯一性。遍歷原數(shù)組時,用 Map.has() 判斷元素是否已存在,不存在則用 Map.set() 存儲,并加入新數(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); // 存儲元素(值隨便設,只要有標記即可)
   uniqueArr.push(item);
 }
}
console.log(uniqueArr); // 輸出:[1, 2, "3", 4]

優(yōu)缺點

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

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

適用場景

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

六、復雜場景:引用類型(對象 / 數(shù)組)去重

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

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

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

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

方法 2:手動比較屬性(復雜對象適用)

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

const arr = [
 { id: 1, name: "小明" },
 { id: 1, name: "小明" },
 { id: 2, name: "小紅" }
];
const uniqueArr = [];
for (let item of arr) {
 // 用 some 判斷新數(shù)組中是否已有相同 id 的對象
 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)缺點

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

  • 缺點JSON.stringify 有局限性(比如無法處理 function、undefinedSymbol 等屬性);手動比較屬性需指定唯一標識,靈活性較低。

適用場景

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

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

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

代碼實現(xiàn)

const arr = [3, 1, 2, 2, 3, 1, 4];
const uniqueArr = [];
// 先排序(注意:sort 默認按字符串排序,數(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++) {
 // 比較當前元素和前一個元素,不同則保留
 if (sortedArr[i] !== sortedArr[i - 1]) {
   uniqueArr.push(sortedArr[i]);
 }
}
console.log(uniqueArr); // 輸出:[1, 2, 3, 4]

優(yōu)缺點

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

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

適用場景

處理數(shù)字數(shù)組,且不關心原數(shù)組順序的場景。

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

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

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

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

相關文章

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

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

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

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

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

    js a標簽點擊事件

    本文將詳細介紹a標簽上的點擊事件的相關知識。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-03-03
  • Javascript oop設計模式 面向?qū)ο缶幊毯唵螌嵗榻B

    Javascript oop設計模式 面向?qū)ο缶幊毯唵螌嵗榻B

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

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

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

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

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

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

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

    BootStrap 動態(tài)添加驗證項和取消驗證項的實現(xiàn)方法

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

    JavaScript判斷是否手機瀏覽器的五種方法

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

    工作中常用到的ES6語法

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

最新評論

砚山县| 宾阳县| 教育| 安化县| 修文县| 彰化市| 哈尔滨市| 德格县| 莱州市| 赣榆县| 金坛市| 株洲县| 精河县| 鄄城县| 宾阳县| 雷州市| 黔西县| 满城县| 平安县| 措勤县| 赫章县| 布拖县| 巫溪县| 商南县| 永年县| 奉化市| 山西省| 清新县| 维西| 称多县| 巴青县| 乐清市| 巴南区| 石台县| 同江市| 濮阳市| 清新县| 迭部县| 周至县| 夏河县| 樟树市|