关于如何去除一个给定数组中的重复项,应该是 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 }, [])