js 处理对象数组去重?

const a = [
    {name: 'xiaoming', time1: 100, time2: 200},
{name: 'xiaoming', time1: 100, time2: 200},
{name: 'li', time1: 100, time2: 200},
{name: 'zi', time1: 100, time2: 200}]

如何按照姓名相同的人员time1 与time2相加,只保留一个,去重

预期
[
{name: 'xiaoming', time1: 200, time2: 400},
{name: 'li', time1: 100, time2: 200},
{name: 'zi', time1: 100, time2: 200}
]

阅读 2.4k
6 个回答
a.reduce((arr, item) => {
    let res = arr.find(citem => citem.name === item.name)
    if(res){
        res.time1 += item.time1 || 0
        res.time2 += item.time2 || 0
    }else{
        arr.push(item)
    }
    return arr
}, [])

难道已经学到不会用 forEach 了?

const a = [
    {name: 'xiaoming', time1: 100, time2: 200},
{name: 'xiaoming', time1: 100, time2: 200},
{name: 'li', time1: 100, time2: 200},
{name: 'zi', time1: 100, time2: 200}]


const result = [];
a.forEach(item => {
    const _index = result.findIndex(i => i.name === item.name)
    if(_index > -1) {
        result[_index].time1 += item.time1
        result[_index].time2 += item.time2
     } else {
        result.push(item)
    }
});

很简单啊,直接用 Map 跑一次循环,然后再展开就可以了。

const sourceData = [
  {name: 'xiaoming', time1: 100, time2: 200},
  {name: 'xiaoming', time1: 100, time2: 200},
  {name: 'li', time1: 100, time2: 200},
  {name: 'zi', time1: 100, time2: 200}
]
const tmp = new Map(sourceData.map(item=>([`${item.name}-${item.time1+item.time2}`, item])))
const newData = [...tmp.values()]

console.log(newData)
// (3) [{…}, {…}, {…}]
// 0: {name: 'xiaoming', time1: 100, time2: 200}
// 1: {name: 'li', time1: 100, time2: 200}
// 2: {name: 'zi', time1: 100, time2: 200}

因为 SetMapKey 键是不能重复的,所以可以直接用来去重。

function combineArr(arr, combineKey = 'name') {
  let map = {}
  let result = []
  
  arr.forEach(item => {
    if (!map[item[combineKey]]) {
      map[item[combineKey]] = item
      
      result.push(map[item[combineKey]])
      return
    }
    
    Object.keys(map[item[combineKey]]).forEach(key => {
      if (key !== combineKey) {
        map[item[combineKey]][key] += item[key]
      }
    })
    
  })
  
  return result
}

如果只是简单的去重,那可以通过object来实现。

const dataObj = {}
const result = []
for (let i = 0; i < data.length; i++) {
  if (!dataObj[data[i].name]) {
    result.push(data[i])
  }
}

但你是想去重的同时,对重复的数据相加。
此时如果不借助reduce或者forEach,那就需要两次循环,数据量大的时候,性能就没那么好了。

const dataObj = {}
const result = []
for (let i = 0; i < data.length; i++) {
  if (!dataObj[data[i].name]) {
    dataObj[data[i].name] = data[i]
  } else {
    dataObj[data[i].name].time1 += data[i].time1
    dataObj[data[i].name].time2 += data[i].time2
  }
}
for (let p in dataObj) {
  result.push(dataObj[p])
}

如果是借助reduce或者forEach,就是一二楼的写法了。

function isNumber(num) {
  return Object.prototype.toString.call(num).slice(8, -1) === 'Number'
}

function mergeArr(arr, mergeKey) {
  const map = new Map()
  arr.forEach((item) => {
    if (map.has(item[mergeKey])) {
      const target = map.get(item[mergeKey])
      
      for (const key in item) {
        if (key !== mergeKey) {
          if (target.hasOwnProperty(key) && isNumber(target[key]) && isNumber(item[key])) {
            target[key] += item[key]
          } else {
            target[key] = item[key]
          }
        }
      }
      
    } else {
      map.set(item[mergeKey], Object.assign({}, item))
    }
  })
  return Array.from(map.values())
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏