雙重迴圈
- 雙重迴圈是利用兩個for迴圈來實現陣列去重的,相容性最好,但是如果陣列的資料過於龐大的時候,效能不佳。
function unique(array) {
let result = []
for(var i = 0; i < array.length; i++){
for(var j = 0; j < result.length; j ++){
if (array[i] === result[j]) {
// 如果result中有和array[i]相同的項,直接跳出迴圈不再繼續,並且j不會自增
// j 不自增,就意味著,j不會等於result.length,下面的if語句就不會執行
break
}
}
// 如果result中沒有與array[i]相同的項,那麼第二層for迴圈完畢之後,j === result.length
// 並將這輪迴圈的 array[i] push 到result中
if (j === result.length) {
result.push(array[i])
}
}
return result
}
複製程式碼
使用indexOf()方法
- 通過indexOf()方法,來判斷陣列中是否存在指定的值,找到之後返回下標,沒有找到則返回 -1
function unique(array) {
var res = []
for (var i = 0; i < array.length; i ++){
if (res.indexOf(array[i]) === -1) {
res.push(array[i])
}
}
return res
}
複製程式碼
ES5的filter()方法結合indexOf()方法去重
- filter()方法可以過濾陣列,返回過濾後的陣列,且不改變原陣列
function unique(array) {
return array.filter((item, index, self) => self.indexOf(item) === index)
// [1,1,1,1].indexOf(1)返回的是第一個'1'的下標0,不會再查詢第一個 '1' 後面的元素了。
// 在這裡,self.indexOf(item)每次返回的都是下標0,除了第一個元素(index = 0),之後等式都不成立了。
}
複製程式碼
通過物件的key-value來實現去重
- 物件有個hasOwnProperty()方法,用來查詢物件是否含有某個key,返回布林值
- 注意,如果我們定義一個如下的物件,結果會是什麼呢 ?
var obj = {
1: 'number1',
'1': 'string1'
}
複製程式碼
- 答案是字串'1'會將數字1覆蓋,知道這個小細節之後,我們再來實現去重的方法。
function unique(array) {
var obj = {}
return array.filter((item, index, self) => {
// 如果物件中沒有找到 typeof item + item, 則向其新增一個 key: typeof item + item,value設定為true,表示將item過濾出來。
// value可以隨便設定,除了0,'',undefined等等這些會轉化成false值的值
return obj.hasOwnProperty(typeof item + item) ? false : obj[typeof item + item] = true
})
}
複製程式碼
最後我們可以採用ES6中的一種新的資料結果Set,它類似於陣列,但是它的項都是唯一的,沒有重複的值。
Set本身是一個建構函式,用來生成 Set 資料結構。
-
Set 結構的例項有以下屬性。
- Set.prototype.constructor:建構函式,預設就是Set函式。
- Set.prototype.size:返回Set例項的成員總數。
-
Set 例項的方法分為兩大類:操作方法(用於運算元據)和遍歷方法(用於遍歷成員)。
- add(value):新增某個值,返回 Set 結構本身。
- delete(value):刪除某個值,返回一個布林值,表示刪除是否成功。
- has(value):返回一個布林值,表示該值是否為Set的成員。
- clear():清除所有成員,沒有返回值。
- keys():返回鍵名的遍歷器
- values():返回鍵值的遍歷器
- entries():返回鍵值對的遍歷器
- forEach():使用回撥函式遍歷每個成員
var uniqueArr = new Set([1,2,3,1,'1','a','a'])
>>>uniqueArr
<<< Set(5) {1, 2, 3, "1", "a"}
>>> uniqueArr instanceof Array
<<< false
複製程式碼
- 可以看到,返回的結果是Set資料結果,那麼如何返回一個陣列呢?這就要用到ES6提供的另一個陣列方法了
- Array.from(obj, fn, context)方法將一個類陣列物件或者可遍歷物件轉換成一個真正的陣列,它可以接受三個引數,第一個是需要轉化的物件,第二個是一個函式,物件的每一項都會執行這個函式,返回處理後的項,context指定執行fn的this物件
理解用法之後,我們再來看一下如何使用Set來實現陣列去重
function unique(array) {
return Array.from(new Set(array))
}
複製程式碼
當然也可以不使用Array.from()方法,使用ES6 '...' 擴充套件運算子
function unique(array) {
return [...new Set(array)]
}
// 我們可以簡化一下這個函式
var unique = (array) => [...new Set(array)]
複製程式碼
總結:我們看到,陣列去重的方式有很多,但以上都是在處理基本資料型別,但是如果碰到陣列中存在物件的時候,還需要另當別論。看下如下的例子:
>>> NaN === NaN
<<< false
>>> NaN == NaN
<<< false
>>> {} == {}
<<< false
>>> {} === {}
<<< false
>>> undefined == undefined
<<< true
>>> undefined === undefined
<<< true
>>> null == null
<<< true
>>> null === null
<<< true
複製程式碼