js 数组对象怎么根据多个字段分组

发布于 2022-09-12 23:49:35 字数 393 浏览 13 评论 0

原数组

arr = [
{status:1,opp:2,ad:'11'},
{status:1,opp:2,ad:'22'},
{status:1,opp:3,ad:'33'},
{status:2,opp:4,ad:'44'},
{status:3,opp:5,ad:'55'}
]

处理后的数组

arr1 = [
  {status:1,opp:2,add:['11','22']},
  {status:1,opp:3:add:['33']}
]
arr2 = [
  {status:2,opp:4:add:['44']}
]
arr3 = [
  {status:3,opp:5:add:['55']}
]

怎么根据status和opp来判断分组

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

幼儿园老大 2022-09-19 23:49:35

处理过程就是一个“分组 → 映射”,映射过程中再进行一次“分组→映射”。下面是用 Lodash 处理的

import _ from "lodash";

const arr = [
    { status: 1, opp: 2, ad: "11" },
    { status: 1, opp: 2, ad: "22" },
    { status: 1, opp: 3, ad: "33" },
    { status: 2, opp: 4, ad: "44" },
    { status: 3, opp: 5, ad: "55" }
]

const r = _(arr)
    .groupBy("status")
    .values()
    .map(it => _(it)
        .groupBy("opp")
        .values()
        .map(list => ({
            status: list[0].status,
            opp: list[0].opp,
            add: list.map(v => v.ad)
        }))
        .value()
    )
    .value();

console.log(JSON.stringify(r));

看起来每一步都有循环,不过 Lodash 会自己去优化多个循环,不用太 Care。

groupBy 也可以自己写,比如下面这个,如果有 mapper 就对组成员进行映射(返回数组),没有直接返回分组结果对象(返回对象)

function groupBy(arr, keyName, mapper) {
    const groups = {};

    arr.forEach(it => {
        const key = it[keyName];
        (groups[key] ??= []).push(it)
    });

    return mapper
        ? Object.values(groups).map(mapper)
        : groups;
}

调用过程如下:

const r2 = groupBy(
    arr,
    "status",
    listByStatus => {
        return groupBy(
            listByStatus,
            "opp",
            listByOpp => ({
                status: listByOpp[0].status,
                opp: listByOpp[0].opp,
                add: listByOpp.map(it => it.ad)
            })
        )
    });
栀子花开つ 2022-09-19 23:49:35

思路:可以通过一次循环,把arr变成下面的obj对象,通过Object.values(obj)获取对象的value值,就可以了

obj = {
  1:[
      { status: 1, opp: 2, add: ["11","22"] },
      { status: 1, opp: 3, add: ["33"] }
    ],
  2:[{ status: 2, opp: 4, add: ["44"] }],
  3:[{ status: 3, opp: 5, add: ["55"] }]
}

具体代码如下

      let obj = {};
      for (let i = 0; i < arr.length; i++) {
        const { ad, ...other } = arr[i];
        if (!obj[other.status]) obj[other.status] = [];
        const index = obj[other.status].findIndex(
          (ele) => ele.opp === other.opp
        );
        if (index >= 0) obj[other.status][index].add.push(ad);
        else obj[other.status].push({ ...other, add: [ad] });
      }
永言不败 2022-09-19 23:49:35

时间复杂度O(N*Log(N)),其中N为数组长度

const arr = [
  { status: 1, opp: 2, ad: "11" },
  { status: 1, opp: 2, ad: "33" },
  { status: 1, opp: 3, ad: "33" },
  { status: 1, opp: 3, ad: "44" },
  { status: 2, opp: 4, ad: "44" },
  { status: 3, opp: 5, ad: "55" }
];

const group = (arr) => {
  if (!arr.length) return [];
  arr.sort((a, b) => {
    if (a.status === b.status && a.opp === b.opp) return 0;

    if (a.status !== b.status) return a.status - b.status;
    else return a.opp - b.opp;
  });

  let ans = [];
  let prev = { ...arr[0], add: [arr[0].ad] };
  delete arr[0].ad;
  let curGroup = [prev];
  for (let i = 1; i < arr.length; ++i) {
    if (arr[i].status === prev.status) {
      if (arr[i].opp === prev.opp) {
        prev.add.push(arr[i].ad);
      } else {
        prev = { ...arr[i], add: [arr[i].ad] };
        delete arr[i].ad;
        curGroup.push(prev);
      }
    } else {
      ans.push(curGroup);
      curGroup = [{ ...arr[i], add: [arr[i].ad] }];
      delete arr[i].ad;
      prev = arr[i];
    }
  }

  ans.push(curGroup);

  return ans;
};

console.log(group(arr));
一世旳自豪 2022-09-19 23:49:35

其实多看看就可以了

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文