關於如何去除一個給定數組中的重複項,應該是 Javascript 面試中最多見的一個問題了,最多見的方式有三種:Set
、Array.prototype.filter
以及 Array.prototype.reduce
,對於只有簡單數據的數組來說,我最喜歡 Set
,沒別的,就是寫起來簡單。面試
const originalArray = [1, 2, '咩', 1, 'Super Ball', '咩', '咩', 'Super Ball', 4] const bySet = [...new Set(originalArray)] const byFilter = originalArray.filter((item, index) => originalArray.indexOf(item) === index) const byReduce = originalArray.reduce((unique, item) => unique.includes(item) ? unique : [...unique, item], [])
Set
先讓咱們來看看 Set
究竟是個啥數組
Set
對象容許你存儲任何類型的惟一值,不管是原始值或者是對象引用。<cite>https://developer.mozilla.org...</cite>函數
Set
中只容許出現惟一值const bySet = [...new Set(originalArray)]
這一段的操做,咱們將它拆分來看:測試
const originalArray = [1, 2, '咩', 1, 'Super Ball', '咩', '咩', 'Super Ball', 4] const uniqueSet = new Set(originalArray) // 獲得 Set(5) [ 1, 2, "咩", "Super Ball", 4 ] const bySet = [...uniqueSet] // 獲得 Array(5) [ 1, 2, "咩", "Super Ball", 4 ]
在將 Set
轉爲 Array
時,也可使用 Array.from(set)
。this
Array.prototype.filter
要理解 filter
方法爲何能夠去重,須要關注一下另外一個方法 indexOf
prototype
indexOf()
方法返回在數組中能夠找到一個給定元素的第一個索引,若是不存在,則返回-1
。<cite>https://developer.mozilla.org...</cite>code
const beasts = ['ant', 'bison', 'camel', 'duck', 'bison']; console.log(beasts.indexOf('bison')); // expected output: 1 // start from index 2 console.log(beasts.indexOf('bison', 2)); // expected output: 4 console.log(beasts.indexOf('giraffe')); // expected output: -1
filter()
方法建立一個新數組, 其包含經過所提供函數實現的測試的全部元素。<cite>https://developer.mozilla.org...</cite>對象
filter
方法接受兩個參數:索引
filter
會將數據中的每一項都傳遞給該函數,若該函數返回 真值,則數據保存,返回 假值,則數據將不會出如今新生成的數據中this
的指向咱們將上面的去重方法按下面這樣重寫一下,就能夠看清整個 filter
的執行過程了。ip
const originalArray = [1, 2, '咩', 1, 'Super Ball', '咩', '咩', 'Super Ball', 4] const table = [] const byFilter = originalArray.filter((item, index) => { // 若是找到的索引與當前索引一致,則保留該值 const shouldKeep = originalArray.indexOf(item) === index table.push({ 序號: index, 值: item, 是否應該保留: shouldKeep ? '保留' : '刪除' }) return shouldKeep }) console.log(byFilter) console.table(table)
序號 | 值 | 是否應該保留 | - |
0 | 1 | 保留 | 第一次出現 |
1 | 2 | 保留 | 第一次出現 |
2 | 咩 | 保存 | 第一次出現 |
3 | 1 | 刪除 | 第二次出現 |
4 | Super Ball | 保留 | 第一次出現 |
5 | 咩 | 刪除 | 第二次出現 |
6 | 咩 | 刪除 | 第三次出現 |
7 | Super Ball | 刪除 | 第二次出現 |
8 | 4 | 保留 | 第一次出現 |
Array.prototype.reduce
reduce()
方法對數組中的每一個元素執行一個由您提供的reducer
函數(升序執行),將其結果彙總爲單個返回值。<cite>https://developer.mozilla.org...</cite>
Array.prototype.reduce
方法接受兩個參數:
Callback
:回調函數,它能夠接收四個參數
Accumulator
:累計器,這個實際上是讓不少人忽略的一點,就是,累計器其實能夠是任何類型的數據 Current Value
:當前值Current Index
:當前值的索引Source Array
:源數組Initial Value
:累計器的初始值,就跟累計器同樣,這個參數也老是被絕大多數人忽略 就像 filter
章節同樣,咱們來看看 reduce
的執行過程:
const originalArray = [1, 2, '咩', 1, 'Super Ball', '咩', '咩', 'Super Ball', 4] const byReduce = originalArray.reduce((unique, item, index, source) => { const exist = unique.includes(item) const next = unique.includes(item) ? unique : [...unique, item] console.group(`遍歷第 ${index} 個值`) console.log('當前累計器:', unique) console.log('當前值:', item) console.log('是否已添加進累計器?', exist) console.log('新值', next) console.groupEnd() return next }, [])