js将一个数组相同value数据合并重组

新手上路,请多包涵

原数组:

 const arr = [
      { name: "语文", date: "2016", value: "148" },
      { name: "数学", date: "2016", value: "153" },
      { name: "英语", date: "2016", value: "205" },
      { name: "语文", date: "2017", value: "126" },
      { name: "数学", date: "2017", value: "146" },
      { name: "英语", date: "2017", value: "214" },
      { name: "语文", date: "2018", value: "132" },
      { name: "数学", date: "2018", value: "152" },
      { name: "英语", date: "2018", value: "223" },
      { name: "语文", date: "2019", value: "135" },
      { name: "数学", date: "2019", value: "140" },
      { name: "英语", date: "2019", value: "202" },
      { name: "语文", date: "2020", value: "109" },
      { name: "数学", date: "2020", value: "130" },
      { name: "英语", date: "2020", value: "109" }]

目标数组

const newArr = [
      {
        date: 2016,
        yuwen: 123,
        shuxue: 123,
        yingyu: 512
      },
      {
        date: 2017,
        yuwen: 123,
        shuxue: 123,
        yingyu: 512
      },
      ...
    ]
阅读 4k
3 个回答
Object.values(arr.reduce((res,v) => {
  const item = res[v.date] ||= {date: v.date}
  item[v.name] = v.value;
  return res;
}, {}))
function merge(arr) {
    var ret = [];
    loop: for (var i = 0; i < arr.length; ++i) {
        for (var j = 0; j < ret.length; ++j) {
            if (ret[j].date === arr[i].date) {
                ret[j][arr[i].name] = arr[i].value;
                continue loop;
            }
        }
        var obj = { date: arr[i].date };
        obj[arr[i].name] = arr[i].value;
        ret.push(obj);
    }
    return ret;
}
console.dir(merge(arr));

分步思路,用 Lodash 处理

const r = _(arr)
    // 按日期分组,分组得到对象,其键是分组属性 date,值是符合分组条件的元素组合(数组)
    .groupBy(it => it.date)
    // 将每组(数组)的元素合并成对象,mapValues
    .mapValues((group, date) => ({
        date,
        // 将原结构元素的 name 和 value 拿出来组成 [key, value] 对,再生成对象(合并成对象)
        ..._(group).map(it => [it.name, it.value]).fromPairs().value()
    }))
    // mapValues 之后分组结果的值(组元素集,数组)已经变成对象,但要把它们都摘出来组成新的数组
    .values()
    // lodash lazy 计算结果
    .value();

感觉 Lodash 会慢一些,手撸一个

const r = arr.reduce((result, el) => {
    let group = result.find(it => it.date === el.date);
    if (!group) {
        group = { date: el.date };
        result.push(group);
    }
    // 上面几句可以写成一句
    // const group = result.find(it => it.date === el.date) ?? (result[result.length] = { date: el.date });
    group[el.name] = el.value;
    return result;
}, []);

测试效率对比(这算是少量数据,大量数据可能会有所不同)

image.png

image.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题