如何让多个对象相同的属性值相加

    var data = [
      {
        typeId: '2',
        name: 'potato',
        number: 16
      },
      {
        typeId: '3',
        name: 'potato',
        number: 10
      },
      {
        typeId: '4',
        name: 'tomato',
        number: 4
      },
      {
        typeId: '5',
        name: 'tomato',
        number: 21
      },
      {
        typeId: '6',
        name: 'vegetables',
        number: 3
      },
      {
        typeId: '7',
        name: 'vegetables',
        number: 13
      },
    ]
转换成以下数据 arr数据
    arr = [
      {
        typeId: ["6", "7"],
        name: 'vegetables',
        number: 16
      },
      {
        typeId: ["4", "5"],
        name: 'tomato',
        number: 25
      },
      {
        typeId: ["2", "3"],
        name: 'potato',
        number: 26
      }
    ]

把 数组 data中的子对象中 name属性相同的子对象的 number 合并,得到一个新的对象,从而返回一个新数组 arr, 有哪些比较好的方法?

阅读 6.3k
7 个回答

GroupBy 啊。会写 groupBy 之后你可以回答 js 话题下的大部分 json 遍历转化问题。

不知道将来 JS 的数组会不会加原生的 GroupBy 实现。

// 这个 groupBy 函数是通用的,无论需求怎么变,groupBy的实现不会变
function groupBy(arr, by) {
    return arr.reduce((groups, item) => {
        // 获取 item 的分组的 key
        const key = by(item);
        // 看看这个组是不是已经存在
        let group = groups.find(g => g.key === key);
        if(!group) {
            // 不存在就创建一个新组
            group = {key, items: []};
            groups.push(group);
        }
        // item 放入组中
        group.items.push(item);
        return groups;
    }, []);
}

// 就是 SQL 的翻版嘛
// select name, sum(number) from data group by name
groupBy(data, item => item.name)
    .map(g => ({
        name: g.key,
        typeId: g.items.map(item => item.typeId),
        number: g.items.reduce((sum, item) => sum + item.number, 0)
    }));
var data = [
      {
        typeId: '2',
        name: 'potato',
        number: 16
      },
      {
        typeId: '3',
        name: 'potato',
        number: 10
      },
      {
        typeId: '4',
        name: 'tomato',
        number: 4
      },
      {
        typeId: '5',
        name: 'tomato',
        number: 21
      },
      {
        typeId: '6',
        name: 'vegetables',
        number: 3
      },
      {
        typeId: '7',
        name: 'vegetables',
        number: 13
      },
    ]
      let arr = []
      data.map((el,i) => {

          if(!arr.some(el2 => el2.name === el.name)){
            arr.push({
                typeId:[el.typeId],
                name:el.name,
                number:el.number
            })
          }else{
              let obj = arr.find(v => v.name === el.name)
              obj.typeId.push(el.typeId)
              obj.number = obj.number + el.number
          }
      })
      console.log(arr)
const res = [];
data.map((ele, index, arr) => {
    if (!res.find(newE => ele.name == newE.name)) {
        let typeArr = [ele.typeId]
        let num = ele.number;
        for (let i in arr) {
            if (ele.name == arr[i].name && i != index) {
                typeArr.push(arr[i].typeId);
                num += arr[i].number;
            }
        }
        ele.typeId = typeArr;
        ele.number = num;
        res.push(ele);
    }
})

console.log(res);
const subscripts = {};
const result = [];

data.forEach(({ name, typeId, number }) => {
    const idx = subscripts[name];
    
    if (typeof idx === 'number') {
        result[idx].number += number;
        result[idx].typeId.push(typeId);
    } else {
        subscripts[name] = result.length;
        result.push({ typeId: [typeId], name, number });
    }
});
function concatSameProp (data) {
  return data.reduce((prev, cur) => {
    if (!prev.length || !prev.filter(x => x.name === cur.name).length) {
      cur.typeId = cur.typeId.split('')
      prev.push(cur)
      return prev
    } else {
      const idx = prev.findIndex(x => x.name === cur.name)
      prev[idx].typeId.push(cur.typeId)
      prev[idx].number += cur.number
      return prev
    }
  }, [])
}

concatSameProp(data)
data.reduce((acc, cur) => {
  let item = acc.find((item) => item.name === cur.name)
  if (item) {
    item.typeId = [...item.typeId, cur.typeId]
    item.number += cur.number
  } else {
    acc.push({
      ...cur,
      typeId: [cur.typeId],
    })
  }
  return acc
}, [])
let res = data.reduce((prev, next, index) => {
    const {typeId,name,number} = next;
    //如果当前 蔬菜 已经存在则对应赋值
    if (prev[name])(prev[name].number += number,prev[name].typeId.push(typeId))
    //否则就初始化当前 蔬菜
    else(prev[name] = {...next,typeId: [typeId]})
    //最后一项返回 格式化后的数据
    if (index === data.length - 1) return Object.entries(prev).map(([key,value]) => value)
    return prev
}, {})
console.log(res)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题