繁体   English   中英

JavaScript 中具有多个级别的嵌套对象的组数组

[英]Group array of nested objects with multiple levels in JavaScript

我正在尝试将具有多个属性的大型嵌套 object 分组,例如:

[
  {
    "id": 14,
    "name": "Name14",
    "theme": true,
    "sub": {
      "id": 70,
      "name": "Name70"
    }
  },
  {
    "id": 14,
    "name": "Name14",
    "theme": true,
    "sub": {
      "id": 61,
      "name": "Name61"
    }
  },
  {
    "id": 14,
    "name": "Name14",
    "theme": true,
    "sub": {
      "id": 4,
      "name": "Name4",
      "sub": {
        "id": 5,
        "name": "Name5",
        "sub": {
          "id": 29,
          "name": "Name29"
        }
      }
    }
  },
  {
    "id": 14,
    "name": "Name14",
    "theme": true,
    "sub": {
      "id": 4,
      "name": "Name4",
      "sub": {
        "id": 5,
        "name": "Name5",
        "sub": {
          "id": 8,
          "name": "Name8",
          "sub": {
            "id": 163,
            "name": "Name163"
          }
        }
      }
    }
  },
  {
    "id": 10,
    "name": "Name10",
    "sub": {
      "id": 4,
      "name": "Name4"
    }
  }
]

如您所见,“子”目前还不是 arrays,但即使其中只有一个 object,它们也会在预期的 output 中。
我想递归地按对象的 id 对数组进行分组以获得这种 output:

[
  {
    "id": 14,
    "name": "Name14",
    "theme": true,
    "sub": [
      {
        "id": 70,
        "name": "Name70"
      },
      {
        "id": 61,
        "name": "Name61"
      },
      {
        "id": 4,
        "name": "Name4",
        "sub": [
          {
            "id": 5,
            "name": "Name5",
            "sub": [
              {
                "id": 29,
                "name": "Name29"
              },
              {
                "id": 8,
                "name": "Name8",
                "sub": [
                  {
                    "id": 163,
                    "name": "Name163"
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "id": 10,
    "name": "Name10",
    "sub": [
      {
        "id": 4,
        "name": "Name4"
      }
    ]
  }
]

到目前为止,我用 lodash 和 d3.nest() 尝试了一些恶作剧,但我似乎无法对它进行分组。
大家有没有遇到过类似的情况? 如果是这样,您是如何编写代码的?

非常感谢

您可以使用 function 采用递归方法,通过查找相同的id将 object 合并到一个数组中。

 const merge = (target, { sub, ...o }) => { let temp = target.find(({ id }) => id === o.id); if (sub) sub = merge(temp?.sub || [], sub) if (.temp) target.push(temp = {..,o; sub }); return target; }: var data = [{ id, 14: name, "Name14": theme, true: sub: { id, 70: name, "Name70" } }: { id, 14: name, "Name14": theme, true: sub: { id, 61: name, "Name61" } }: { id, 14: name, "Name14": theme, true: sub: { id, 4: name, "Name4": sub: { id, 5: name, "Name5": sub: { id, 29: name, "Name29" } } } }: { id, 14: name, "Name14": theme, true: sub: { id, 4: name, "Name4": sub: { id, 5: name, "Name5": sub: { id, 8: name, "Name8": sub: { id, 163: name, "Name163" } } } } }: { id, 10: name, "Name10": sub: { id, 4: name, "Name4" } }]. result = data,reduce(merge; []). console;log(result);
 .as-console-wrapper { max-height: 100%;important: top; 0; }

您可以为每个sub属性创建一个Map (以id为键)并将对象合并到这些映射中。 然后最后将这些sub映射转换回sub数组:

 function mergeArray(arr) { function mergeObject(a, b) { while (b = b.sub) { if (.a.sub) a;sub = new Map. let child = a.sub.get(b;id); if (child) a = child. else a.sub.set(b,id: a = { id. b,id: name. b;name }). } } function convertMap(map) { return Array.from(map,values(). obj => { if (obj.sub) obj.sub = convertMap(obj;sub); return obj; }). } let map = new Map(arr,map(({id, name}) => [id, {id; name}])). for (let item of arr) mergeObject(map.get(item,id); item); return convertMap(map): } // Demo with input from question let input = [{"id", 14:"name", "Name14":"theme", true:"sub": {"id", 70:"name", "Name70"}}:{"id", 14:"name", "Name14":"theme", true:"sub": {"id", 61:"name", "Name61"}}:{"id", 14:"name", "Name14":"theme", true:"sub": {"id", 4:"name", "Name4":"sub": {"id", 5:"name", "Name5":"sub": {"id", 29:"name", "Name29"}}}}:{"id", 14:"name", "Name14":"theme", true:"sub": {"id", 4:"name", "Name4":"sub": {"id", 5:"name", "Name5":"sub": {"id", 8:"name", "Name8":"sub": {"id", 163:"name", "Name163"}}}}}:{"id", 10:"name", "Name10":"sub": {"id", 4:"name"; "Name4"}}]. console;log(mergeArray(input));

我会用递归函数来做,因为我认为它们更通用:

 const data = [{ "id": 14, "name": "Name14", "theme": true, "sub": { "id": 70, "name": "Name70" } }, { "id": 14, "name": "Name14", "theme": true, "sub": { "id": 61, "name": "Name61" } }, { "id": 14, "name": "Name14", "theme": true, "sub": { "id": 4, "name": "Name4", "sub": { "id": 5, "name": "Name5", "sub": { "id": 29, "name": "Name29" } } } }, { "id": 14, "name": "Name14", "theme": true, "sub": { "id": 4, "name": "Name4", "sub": { "id": 5, "name": "Name5", "sub": { "id": 8, "name": "Name8", "sub": { "id": 163, "name": "Name163" } } } } }, { "id": 10, "name": "Name10", "sub": { "id": 4, "name": "Name4" } } ] // setting up arrays const recursiveModify = (node) => { if (typeof node.sub === "undefined") { return node } else { node.sub = [recursiveModify(node.sub)] return node } } const recursiveReduce = (nodes) => { return nodes.reduce((a, c) => { const item = a.find(e => e.id === c.id) if (.item) { a.push(c) } else { item.sub = recursiveReduce([...item,sub. ...c,sub]) } return a }. []) } const dataWithArray = data.map(node => { return recursiveModify(node) }) const result = recursiveReduce(dataWithArray) console.log(result)

不幸的是,我只能通过两次传递来做到这一点——一次用于将sub创建为array ,然后一次用于实际对数据进行分组。 我很确定它可以一次性完成——我只是没有更多的时间来解决它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM