您好,登錄后才能下訂單哦!
這篇“JavaScript怎么實現(xiàn)數(shù)組去重”文章,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要參考一下,對于“JavaScript怎么實現(xiàn)數(shù)組去重”,小編整理了以下知識點,請大家跟著小編的步伐一步一步的慢慢理解,接下來就讓我們進入主題吧。
1.JavaScript主要用來向HTML頁面添加交互行為。 2.JavaScript可以直接嵌入到HTML頁面,但寫成單獨的js文件有利于結(jié)構(gòu)和行為的分離。 3.JavaScript具有跨平臺特性,在絕大多數(shù)瀏覽器的支持下,可以在多種平臺下運行。
一、雙層循環(huán)
const unique = (arr)=>{ for(let i = 0; i < arr.length; i++){ for(let j = i + 1; j < arr.length; j++){ if(arr[i] === arr[j]){ arr.splice(j, 1); // 移除重復元素 j--; // 修正下標 } } } return arr;};const unique = (arr)=>{ var arr = [1, '1', '1', 1, 2, true, false, true, 3, 2, 2, 1]; var newArr = []; for(let i = 0; i < arr.length; i++){ for(var j = 0; j < newArr.length; j++){ // 注意var聲明的j if(arr[i] === newArr[j]) break; // 新數(shù)組已存在當前值 } if(j === newArr.length){ // 此時j和newArr長度相等,沒有被中斷 newArr.push(arr[i]); } } return newArr;}unique([1, '1', '1', 1, 2, true, false, true, 3, 2, 2, 1]); // [ 1, '1', 2, true, false, 3 ]
核心點:
時間復雜度:O(n^2)
上面的兩種方法都是兩次循環(huán)遍歷,處理方式略有不同
上述實現(xiàn)方式確實不是最佳選擇,但它勝在兼容性好啊~
二、indexOf和includes
核心點:
如果需要返回原數(shù)組,則可以在indexOf
方法找到重復項時(不等于它首次出現(xiàn)的位置)時利用splice
移除
indexOf
:返回在數(shù)組中可以找到一個給定元素的第一個索引
,如果不存在,則返回-1。
indexOf(ele, fromIndex)
ele:要查找的元素
fromIndex:查找元素的起始位置,默認為0,允許負數(shù),-2表示從倒數(shù)第二個元素開始查找
返回一個下標(number)
代碼:
const unique = (arr) => { var res = []; for (let i = 0; i < arr.length; i++){ if(res.indexOf(arr[i]) === -1 ){ res.push(arr[i]); } } return res;}
核心點:
具體的是要返回原數(shù)組還是新數(shù)組大家可以自行組合~
includes
:用來判斷一個數(shù)組是否包含一個指定的值,根據(jù)情況,如果包含則返回 true
,否則返回false
includes(ele, fromIndex)
ele:要查找的元素
fromIndex:指定索引處開始查找。默認為 0,如果為負值,從末尾開始往前跳 fromIndex
的絕對值個索引。。
返回結(jié)果(bool)
代碼:
const unique = (arr) => { var res = []; for (let i = 0; i < arr.length; i++){ if(!res.includes(arr[i])){ res.push(arr[i]); } } return res;}
在這里我們推薦使用includes來查找元素:
返回值可以直接作為if的條件語句,簡潔
if(res.indexOf(arr[i]) !== -1 ){ todo }// orif(res.includes(arr[i])){ todo }
識別NaN
如果數(shù)組中有NaN
,你又正好需要判斷數(shù)組是否有存在NaN
,這時你使用indexOf
是無法判斷的,你必須使用includes
這個方法。
var arr = [NaN, NaN];arr.indexOf(NaN); // -1arr.includes(NaN); // true
識別undefined
如果數(shù)組中有undefined
值,includes
會認為空的值是undefined,而indexOf
不會。
var arr = new Array(3);console.log(arr.indexOf(undefined)); //-1console.log(arr.includes(undefined)) //true
三、排序去重
核心點:
數(shù)組排序后,相同的元素會相鄰,所以如果當前元素與它的相鄰元素不同,就存入到新數(shù)組中;
相比于indexOf,只需要一層循環(huán);
concat會拼接數(shù)組,并返回新數(shù)組;
sort()排序是通過按照轉(zhuǎn)換為的字符串的各個字符的Unicode位點
進行排序。所以很難保證它的準確性;
代碼:
var arr = [1, 1, '1'];function unique(arr) { var res = []; var sortedArr = arr.concat().sort(); var last; for (var i = 0; i < sortedArr.length ; i++) { // 如果是第一個元素或者相鄰的元素不相同 if (!i || last !== sortedArr[i]) { res.push(sortedArr[i]) } last = sortedArr[i]; // 記錄上一個值 } return res;}console.log(unique(array));
四、filter
核心點:
filter:方法創(chuàng)建一個新數(shù)組, 其包含通過所提供函數(shù)實現(xiàn)的測試
的所有元素(返回測試函數(shù)成立的元素)
filter(callback, thisArg)
:
callback接受三個參數(shù):element-當前正在處理的元素,index-當前元素索引,array-調(diào)用了filter的數(shù)組本身
thisArg:執(zhí)行 callback 時,用于 this 的值。
利用filter我們可以在代碼層面簡化一下外層循環(huán):
代碼:
var arr = [1, 2, 1, 1, '1'];const unique = function (arr) { var res = arr.filter(function(item, index, arr){ return arr.indexOf(item) === index; }) return res;}console.log(unique(arr)); // [ 1, 2, '1' ]
結(jié)合排序的思路:
var arr = [1, 2, 1, 1, '1'];const unique = function (arr) { return arr.concat().sort().filter(function(item, index, arr){ return !index || item !== arr[index - 1] })}console.log(unique(arr));
五、鍵值對(key-value)
前面提到的幾種方式總結(jié)下來大致分為
非排序數(shù)組,兩次遍歷判斷(遍歷、查詢)
排序數(shù)組,相鄰元素比較
我們再提出一種方式,利用Object對象 key-value的方式,來統(tǒng)計數(shù)組中元素出現(xiàn)的個數(shù),初步判斷邏輯也有兩種
拿[1,1,1,2,2,3,'3']
舉例:
統(tǒng)計每個元素出現(xiàn)的次數(shù),obj:{1: 3, 2: 2, 3: 3}, 返回這個obj
的key
而不管他們的value
只元素首次出現(xiàn),再次出現(xiàn)則證明他是重復元素
var arr = [1, 2, 1, 1, '1', 3, 3];const unique = function(arr) { var obj = {}; var res = []; arr.forEach(item => { if (!obj[item]) { obj[item] = true; res.push(item); } }); return res;}console.log(unique(arr)); // [1, 2, 3]
var arr = [1, 2, 1, 1, '1'];const unique = function(arr) { var obj = {}; return arr.filter(function(item, index, arr){ return obj.hasOwnProperty(item) ? false : (obj[item] = true) })}console.log(unique(arr)); // [1, 2]
對象的屬性是字符串類型的,即本身數(shù)字1
和字符串‘1’
是不同的,但保存到對象中時會發(fā)生隱式類型轉(zhuǎn)換,導致去重存在一定的隱患。
考慮到string和number的區(qū)別(typeof 1 === ‘number’, typeof ‘1’ === ‘string’),
所以我們可以使用 typeof item + item
拼成字符串作為 key 值來避免這個問題:
var arr = [1, 2, 1, 1, '1', 3, 3, '2'];const unique = function(arr) { var obj = {}; var res = []; arr.forEach(item => { if (!obj[typeof item + item]) { obj[typeof item + item] = true; res.push(item); } }); return res;}console.log(unique(arr)); // [ 1, 2, '1', 3, '2' ]
六、ES6
隨著 ES6 的到來,去重的方法又有了進展,比如我們可以使用 Set 和 Map 數(shù)據(jù)結(jié)構(gòu)。
Set:它允許你存儲任何類型的唯一值,無論是原始值或者是對象引用
代碼:
var arr = [1, 2, 1, '1', '2'];const unique = function(arr) { return Array.from(new Set(arr));}console.log(unique(arr)); // [ 1, 2, '1', '2' ]
簡化1:
function unique(array) { return [...new Set(array)];}
簡化2:
var unique = (a) => [...new Set(a)]
Map 對象保存鍵值對,并且能夠記住鍵的原始插入順序。任何值(對象或者原始值) 都可以作為一個鍵或一個值。
Map.prototype.has(key):返回一個布爾值,表示Map實例是否包含鍵對應的值。
Map.prototype.set(key, value):設置Map對象中鍵的值。返回該Map對象。
function unique (arr) { const newMap = new Map() return arr.filter((a) => !newMap.has(a) && newMap.set(a, 1));}
寫到這里比較常規(guī)的數(shù)組去重方法就總結(jié)的差不多了,如果需要更強大的去重方法,我們需要對他們進行組合,而且因為場景的不同,我們所實現(xiàn)的方法并不一定能涵蓋到
以上是“JavaScript怎么實現(xiàn)數(shù)組去重”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。