liangbus / blogging

Blog to go
10 stars 0 forks source link

数组去重的方法,有哪些? #29

Open liangbus opened 4 years ago

liangbus commented 4 years ago

这也算是一个经典的面试题之一了,自己也被问到过,也就说出了两三个,今天来整理一下网上常用的数组去重方法(一般指 number[] )

声明一个数组 var arr = [2,6,3,11,34,2,34,7,4,56,76,1,8,786,4,34,2,21,1,45,56,7,678,45,3,8,234,2,45,23,41,75]

遍历

最笨的方法,就是对数组进行遍历,不过这需要两层循环,能用,但就效率低了点,而且代码也不少

function unique(arr) {
  const res = []
  const len = arr.length
  for(let i = 0; i < len; i++) {
    let isExist = false
    for(let j = 0; j < res.length; j++){
      if(arr[i] === res[j]) {
        isExist = true
        break
      }
    }
    if(!isExist) res.push(arr[i])
    // use Array.indexOf
    // if(res.indexOf(arr[i]) === -1) {
    //   res.push(arr[i])
    // }
  }
  return res
}

Array.filter 方法

结合 indexOf,indexOf 只会返回第一个元素的 index

function uniqueFilter(arr) {
  return arr.filter((item, index, original) => original.indexOf(item) === index)
}

Map 过滤

通过一个 hash 去把值作为 key 存起来,这里使用了 ES6 新增的 Map,因为如果使用普通的 Object 的话, key 的顺序可能会发生变更,而 Map 则会按加入顺序来排列

function uniqueWithMap (arr) {
  const map = new Map()
  for(let v of arr) {
    if (!map.has(v)) {
      map.set(v, v)
    }
  }
  return [...map.keys()]
}

function uniqueWithObject (arr) {
  const o = {}
  for(let v of arr) {
    if (!o[v]) {
      o[v] = v
    }
  }
  return [...Object.keys(o)].map(i => Number(i))
}
uniqueWithMap(arr) // [2, 6, 3, 11, 34, 7, 4, 56, 76, 1, 8, 786, 21, 45, 678, 234, 23, 41, 75]
uniqueWithObject(arr) // [1, 2, 3, 4, 6, 7, 8, 11, 21, 23, 34, 41, 45, 56, 75, 76, 234, 678, 786]

Set 构造方法

利用 ES6 新特性,一行代码就可以直接对数组去重

[...new Set(arr)] // [2, 6, 3, 11, 34, 7, 4, 56, 76, 1, 8, 786, 21, 45, 678, 234, 23, 41, 75]
Array.from(new Set(arr)) // [2, 6, 3, 11, 34, 7, 4, 56, 76, 1, 8, 786, 21, 45, 678, 234, 23, 41, 75]

以上去重方法,仅针对数字类型数组讨论,假如数据元素是多种类型,上面的方法输出结果则完全不一样,因为每个 api 对对象的过滤处理都有所不同,具体可参考 JavaScript专题之数组去重

值得思考的是 NaN !== NaN 为真。