js 数组嵌套 json,如何将数组按 json 下的某个 key 归类?

如图数组一

image.png

想得到数组二,按 name 进行分类,怎么操作

image.png

阅读 2.4k
3 个回答
// 得到分组对象,其属性名就是分组依据,这里是 name
const grouped = data.reduce(
    (g, it) => {
        (g[it.name] ??= []).push(it);
        return g;
    },
    {}
);

// 把分组对象的 values 取出来就是结果数组
const groupedList = Object.values(grouped);

如果用 Lodash

import _ from "lodash";
const groupedList = _(data).groupBy("name").values().value();

这个算法做出来之后,结果并不是题主那个顺序,而是按 name 首次出现的先后顺序。如果想按题主那个顺序,还需要排个序

排序依据:

const sortRefs = [..."小中大出雷"].map(s => `${s}明`);
// [ '小明', '中明', '大明', '出明', '雷明' ]
groupedList.sort(([{ name: a }], [{ name: b }]) => {
    return sortRefs.indexOf(a) - sortRefs.indexOf(b);
});

这里参数采用了复杂的解构。因为 groupedList 的每个元素是个数组,其 name 都是相同的,只需要取第 1 个的 name 出来进行比较就好了。

不过,如果计算量较大 indexOf(b) 会比较慢,因为它是采用遍历查找的方法来找到索引。如果要快,可以先准备一个映射表

const indexMap = Object.fromEntries(sortRefs.map((name, i) => [name, i]));

groupedList.sort(([{ name: a }], [{ name: b }]) => {
    return indexMap[a] - indexMap[b];
});
let cache = {}, result = []
list.forEach(item => {
    if(cache[item.name]){
        cache[item.name].push(item)
    }else{
        result.push(cache[item.name] = [item])
    }
})
cache = null

console.log(result)

我提供一种新的解决思路吧!

const map = new Map()

const arr = []

arr.forEach(item => map.get(item.name) ? map.get(item.name).push(item) : map.set(item.name,[item]))

const newArr = Array.from(map.values())

当然三元这么用不符合规范,为了代码更优雅些自己抉择!

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