快乐Js之数组去重

快乐Js之数组去重

我们在写业务代码的时候,经常会碰到给复杂数组去重的需求,那么如何帅气的实现数组去重呢?请你看完这篇文。

简单数组去重

饭要一口一口吃,先来看一个简单数组去重吧,鉴于网上数组去重的方法很多,这里只介绍几个我喜欢的。

// 一个简单数组,包含的每一项都是简单类型的值
const list = [11,11,33,2, 'true', true, undefined, null, null, false, 'false', false, NaN, NaN]

// 利用set数据结构去重的特性,大家用的最多的应该就是这种吧
const duplicateRemoval = list => Array.from(new Set(list))

// for循环去重
const duplicateRemoval = list => {
  const arr = []
  list.forEach(item => !arr.includes(item) && arr.push(item))
  return arr
}

// filter 函数去重
const duplicateRemoval = list => {
  return list.filter((item, index, arr) => {
    //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
    return arr.indexOf(item) === index;
  });
}
// 让我们精简一下上面这个函数,很好,非常的完美
const duplicateRemoval = list => list.filter((item, index, arr) => arr.indexOf(item) === index)

// 使用reduce函数去重
const duplicateRemoval = list => list.reduce((accumulator, currentValue) => {
  if (accumulator.indexOf(currentValue) === -1) {
    accumulator.push(currentValue)
  }
  return accumulator
}, [])
// 好的,按照惯例精简一下
const duplicateRemoval = list => list.reduce((acc, cur) => (!acc.includes(cur) && acc.push(cur), acc),[])
复制代码

简单数组去重的写法太多啦,随便一搜就是十种八种的,鉴于我们的主题并不是简单数组去重,所以暂时就写到这吧~

复杂数组按条件去重

// 一个我们经常会碰到的对象数组,我们需要按照某个特定条件去除重复项
const list = [{name: 'lily1', code: '133'},{name: 'lily1', code: '323'},{name: 'lily2', code: '333'},{name: 'lily3', code: '333'},{name: 'lily4', code: '332'},{name: 'lily4', code: '333'}]

// 由于复杂数据结构的特性,我们无法再简单的使用set进行去重了

// 利用filter函数去重
const duplicateRemovalByFilter = (list, key) => {
  const map = {}
  return list.filter(item => {
    let value = item[key]
    // 还是比较好理解的,写一个map来记录筛选项出现的次数,然后当次数为1时返回true,这样筛选出来的就是在数组中只出现过一次的项了
    if(!map[value]) {
      map[value] = 1
    } else {
      map[value] += 1
    }
    return map[value] === 1
  })
}
// 按照惯例精简一下
const duplicateRemovalByFilter = (list, key) => {
  const map = {}
  // 小知识 赋值语句的返回值等于被赋予的那个值
  // let a; // 返回undefined
  // a = 688; // 返回688
  return list.filter(item => !map[item[key]] && (map[item[key]] = true))
}

// 利用reduce函数去重
const duplicateRemovalByReduce = (list,key) => {
  const obj = list.reduce((pre, cur) => {
    // 判断一下 累加器中对应的值是否为undefined,是的话赋上当前的值,不是的话,就保持现状
    pre[cur[key]] = pre[cur[key]] || cur
    return pre
  }, {})
  // 返回obj中可迭代的值数组
  return Object.values(obj)
}
// 同样,我们的精简环节来了
const duplicateRemovalByReduce = (list,key) => {
  // 一位朋友在vue源码中看到的逗号运算符的应用,虽然比较难理解,但是真帅!
  return Object.values(list.reduce((pre, cur) => (pre[cur[key]] = pre[cur[key]] || cur, pre), {}))
}
复制代码

由于我比较懒,复杂数组按条件去重就写这两样了。还有更多的写法,欢迎交流~

一个值得注意的点

精简写法虽然代码量少,看起来非常舒服。但是如果不写注释突然在你的某个业务功能函数里来上这么一段,分分钟能气死你的同事和过了很久之后再看代码的自己。所以我有两点建议:

  1. 一个函数只做一件事,去重函数就只用来去重,把去重函数单独抽出来写成独立的函数,而不是混在业务逻辑里。
  2. 多写注释

感谢阅读,mua~

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享