js 数组根据字段进行数据聚合的问题

后台接口返回数据如下
result

[
        {
          name: "dd",
          bottleType: "C",
        },
        {
          name: "bb",
          bottleType: "C",
        },
        {
          name: "a",
          bottleType: "C",
        },
        {
          name: "dd",
          bottleType: "P",
        },
        {
          name: "dd",
          bottleType: "P",
        },
        {
          name: "dd",
          bottleType: "D",
        },
        {
          name: "dd",
          bottleType: "D",
        },
        {
          name: "dd",
          bottleType: "D",
        },
      ];

要根据bottleType 这个字段进行数据聚合,得到

 [
        {
          name: "dd",
          bottleType: "C",
          num: 3,
        },

        {
          name: "dd",
          bottleType: "P",
          num: 2,
        },

        {
          name: "dd",
          bottleType: "D",
          num: 3,
        },
      ];

求教简单的实现方法

补充

那如果说 之前的 数组data 里面

[
        {
          name: "dd",
          bottleType: "C",
          num: 3,
        },

        {
          name: "dd",
          bottleType: "P",
          num: 2,
        },

        {
          name: "dd",
          bottleType: "D",
          num: 3,
        },
      ];

已经有了数据 后台再返回一波result这个数据 要怎么把新返回的result 追加到 已经有的数据里呢

阅读 4.4k
5 个回答

没啥简单的办法,只能土办法遍历一遍:

arr = arr.reduce((r,v)=>{
    let item = r.find(i=>i.bottleType==v.bottleType);
    item ? item.num ++ : r.push({...v, ...{num:1}});
    return r;
}, [])

接口多次返回,可以把上面代码包装成一个函数:

// 参数1是后台返回的数组,参数2是上次转换的结果
function xxx(arr1, arr2=[]) {
    return arr1.reduce((r,v)=>{
        let item = r.find(i=>i.bottleType==v.bottleType);
        item ? item.num ++ : r.push({...v, ...{num:1}});
        return r;
    }, arr2);
}

// 先预备个变量,表示转换后的结果
let arr = [];

// 只要接口一返回,就执行一下,刷新结果
arr = xxx(接口返回的数组, arr);

updated

const group_data = (data, old_grouped_data) => {
  const old_grouped_entry = Object.fromEntries(old_grouped_data.map(({ bottleType, ...res }) => [ bottleType, res ]))
  return Object.entries(data.reduce((acc, cur) => {
    acc[cur.bottleType] ??= old_grouped_entry[cur.bottleType] ?? { num: 0, name: cur.name }
    acc[cur.bottleType].num ++
    return acc
  }, {})).map(([key, val ]) => ({ bottleType: key, ...val }))
}

image.png

Array.from(arr.reduce((acc,cur)=>{
    if (acc.has(cur.bottleType)){
        let temp = acc.get(cur.bottleType);
        temp.num  = temp.num + 1;
    } else {
        cur.num = 0;
        acc.set(cur.bottleType, cur);
    }
    return acc;
},new Map()).values())

遍历一遍,先用一个对象存储结果,再将对象转为数组,可以避免在循环中查找是否已经插入过相同类型的数据:

const obj = {}
const result = []
let i = 0
const len = data.length
while (i < len) {
  const item = data[i]
  const { bottleType } = item
  if (obj[bottleType]) {
    obj[bottleType].value++
  } else {
    obj[bottleType] = { ...item, num: 1 }
  }
  j++
}
for (const name in obj) {
  result.push(obj[name])
}
function classify(source, target) {
    if (target == null) {
        target = source;
        source = [];
    }
    if (!(source instanceof Array)) source = [];
    if (!(target instanceof Array)) target = [];
    for (var i = 0; i < target.length; ++i) {
        var item = target[i], obj = null;
        if (!item || typeof item !== "object") continue;
        for (var j = 0; j < source.length; ++j) {
            if (source[j].bottleType === item.bottleType) {
                (obj = source[j]).num++;
                break;
            }
        }
        if (!obj) obj = source[source.length] = { num: 1 };
        for (var key in item) obj[key] = item[key];
    }
    return source;
}
var data = classify(result);
classify(data, [{ name: "dd", bottleType: "P" }]);
console.dir(data);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题