數組去重的方式有很多,讓我們從最原始的方式一步步進化到一行代碼搞定 ...
前言
隨著JavaScript提供語法的增多,數組去重方式也越來越多。現在從最原始的方式到最簡潔的方式,一步步進行剖析。
雙重迴圈
數組去重,不就是比較數組元素,去掉重覆出現的麽。最原始的方式不正是雙重迴圈進行比較處理嘛
//測試數據 var test = [1,2,2,10,'1','a','a','b','@','@']; console.log(unique1(test)); //[1,2,10,'1','a','b','@'] function unique1(target) { //雙層迴圈比較數組元素進行去重 var res = []; //存放數據 for(var i = 0 ; i<target.length ; i++){ for(var j = 0,resLen = res.length ; j < resLen ; j++){ if(target[i] === res[j]){ //如果有相同的數據,則break break; } } if(j === resLen){ //res中沒有相同的數據,則存放 res.push(target[i]) } } return res; }
創建res數組存放返回結果;外層迴圈遍歷target中的每一個數組元素,內層迴圈將target中的數組元素與res數組中的每一個值進行對比,如果都不相同,則存放到res中。迴圈完成,返回去重後的數組。這種原始的方式具有良好的相容性
indexof優化內層迴圈
在本慄中使用indexof優化內層迴圈。indexOf()
方法返回在數組中可以找到一個給定元素的第一個索引,如果不存在,則返回-1
var unique4_1 = (target) => [...new Set(target)]; console.log(unique2(test)); //[1,2,10,'1','a','b','@'] function unique2(target) { //indexof簡化內層迴圈 var res = []; //存放數據 for(var i = 0 ; i<target.length ; i++){ if(res.indexOf(target[i]) < 0) //如果res中不存在該元素,返回-1 res.push(target[i]) } return res; }
使用了indexof方法,就不在需要內層迴圈,當然還有其他的方式可以優化內層迴圈了
對象鍵值對優化內層迴圈
對象的鍵不同重覆,這個特性可以用來判斷重覆元素
//測試數據 var test = [1,2,2,10,'1','a','a','b','@','@']; console.log(unique3(test)); //[1,2,10,'a','b','@'] 因為對象鍵是字元串 所以此種方式會認為 1 和 '1' 是相同的 function unique3(target) { //對象鍵值的方式 var obj = {}; var res = target.filter(function(value,index){ return obj.hasOwnProperty(value) ? false : (obj[value] = true); }) return res; }
註意:由於對象的鍵都是字元,所以,無法區分 1 和 '1' ,所以需要再進行修改一下,存放時加上類型判斷。不瞭解類型判斷的可參考上篇博文: http://www.cnblogs.com/shapeY/p/7600460.html
function unique4(target) { //對象鍵值的方式 var obj = {}; var res = target.filter(function(value,index){ return obj.hasOwnProperty(typeof value + value ) ? false : (obj[typeof value + value] = true); }) return res; }
加上了類型判斷, 1 對應為 Number1 , '1' 對應為 String1,即可正常區分開。
filter優化外層迴圈
在本慄中使用filter優化外層迴圈。filter()
方法創建一個新數組, 其包含通過所提供函數實現的測試的所有元素。
var test = [1,2,2,10,'1','a','a','b','@','@']; console.log(unique5(test)); //[1,2,10,'1','a','b','@'] function unique5(target) { //filter簡化外層迴圈 var res = target.filter(function(value,index,array){ return target.indexOf(value) === index //第一次出現則返回true }) return res }
在target上直接進行過濾,如果是該元素第一次出現,則返回true,否則返回false;這樣filter新創建的數組中每個元素只會出現一次,達到了去重的目的。至此我們不再使用for迴圈,代碼量也減少了很多。
Set去重
ES6 提供了新的數據結構 Set。它類似於數組,但是成員的值都是唯一的,沒有重覆的值。這種特性用來數組去重,十分的方便。
var test = [1,2,2,10,'1','a','a','b','@','@']; console.log(unique6(test)); //[1,2,10,'1','a','b','@'] function unique6(target) { //ES6 —— set return [...new Set(target)] }
'...' 是ES6中的擴展運算符,此處的作用是將Set展開為用逗號隔開的參數序列 , 非常簡單的就實現了數組去重。不熟悉 ES6語法的童鞋們,先自行瞭解。如果再用上箭頭函數,真的是一句話就搞定了,如下:
//測試數據 var test = [1,2,2,10,'1','a','a','b','@','@']; var unique6_1 = (target) => [...new Set(target)]; //乾脆利落 console.log(unique6_1(test)); //[1,2,10,'1','a','b','@']
結語
至此,從雙重迴圈的十幾行代碼到最後 set+箭頭函數的一行搞定。從‘繁’到‘簡’都已經實現了數組的去重,代碼量減少的背後是對JavaScript方法的應用。其實核心思路沒變,實現的手段變了而已。