首页 > 解决方案 > Flatten an array of unknown deep objects, with named properties, in Async/Await JavaScript (or better TypeScript)

问题描述

I've already seen that such questions have been answered 1000 times, but I can't get it.

I have an array with various unknown depth objects, only in the property children are/might be more objects of the same schema as the parent object.

I need all objects regardless of their dependency in a list.

Here is an example of the raw data:

[
   {
     "id": "root________",
     "title": "",
     "index": 0,
     "dateAdded": 1607859798059,
     "type": "folder",
     "dateGroupModified": 1607859798494,
     "children": [
       {
         "id": "menu________",
         "title": "Lesezeichen-Menü",
         "index": 0,
         "dateAdded": 1607859798059,
         "type": "folder",
         "parentId": "root________",
         "dateGroupModified": 1607859798427,
         "children": [
           {
             "id": "vzj790Oc5ncn",
             "title": "Mozilla Firefox",
             "index": 0,
             "dateAdded": 1607859798427,
             "type": "folder",
             "parentId": "menu________",
             "dateGroupModified": 1607859798427,
             "children": [
               {
                 "id": "YIjZdOQ4I3nz",
                 "title": "Hilfe und Anleitungen",
                 "index": 0,
                 "dateAdded": 1607859798427,
                 "type": "bookmark",
                 "url": "https://support.mozilla.org/de/products/firefox",
                 "parentId": "vzj790Oc5ncn"
               },
               {
                 "id": "cHfBIRuk3-d0",
                 "title": "Firefox anpassen",
                 "index": 1,
                 "dateAdded": 1607859798427,
                 "type": "bookmark",
                 "url": "https://support.mozilla.org/de/kb/customize-firefox-controls-buttons-and-toolbars?utm_source=firefox-browser&utm_medium=default-bookmarks&utm_campaign=customize",
                 "parentId": "vzj790Oc5ncn"
               },
               {
                 "id": "wBPLt_b_UKWN",
                 "title": "Machen Sie mit",
                 "index": 2,
                 "dateAdded": 1607859798427,
                 "type": "bookmark",
                 "url": "https://www.mozilla.org/de/contribute/",
                 "parentId": "vzj790Oc5ncn"
               },
               {
                 "id": "LngszJqD2COI",
                 "title": "Über uns",
                 "index": 3,
                 "dateAdded": 1607859798427,
                 "type": "bookmark",
                 "url": "https://www.mozilla.org/de/about/",
                 "parentId": "vzj790Oc5ncn"
               }
             ]
           }
         ]
       },
       {
         "id": "toolbar_____",
         "title": "Lesezeichen-Symbolleiste",
         "index": 1,
         "dateAdded": 1607859798059,
         "type": "folder",
         "parentId": "root________",
         "dateGroupModified": 1607859798494,
         "children": [
           {
             "id": "DnLPkDUWf4k7",
             "title": "Erste Schritte",
             "index": 0,
             "dateAdded": 1607859798494,
             "type": "bookmark",
             "url": "https://www.mozilla.org/de/firefox/central/",
             "parentId": "toolbar_____"
           }
         ]
       },
       {
         "id": "unfiled_____",
         "title": "Weitere Lesezeichen",
         "index": 3,
         "dateAdded": 1607859798059,
         "type": "folder",
         "parentId": "root________",
         "dateGroupModified": 1607859798407,
         "children": []
       },
       {
         "id": "mobile______",
         "title": "Mobile Lesezeichen",
         "index": 4,
         "dateAdded": 1607859798081,
         "type": "folder",
         "parentId": "root________",
         "dateGroupModified": 1607859798407,
         "children": []
       }
     ]
   }
 ]

I have written a repeating function that goes through the nested elements recursively, however within the repeater function it is not being called again despite the repeat call.

How do I call the custom async function again in TypeScript? recursively

  repeater = async (node: any): Promise<any> => {
    const summeryRepeater : any[] = [];
    const children = await this.getChildren(node.id);
    if (children.length >= 1) {
      for (const node of children) {
        summeryRepeater.push(node)
        await this.repeater(node)
      }
    }

    return summeryRepeater
  }
  // TODO
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  getTreeList = async (): Promise<any> => {

    const summery : any[] = [];

    const node = await browser.bookmarks.get("root________"); // return non children
    summery.push(node[0])

    const children = await this.getChildren(node[0].id); // return non children
    if (children.length >= 1) {
      for (const node of children) {
        summery.push(node)

        // // Repeat start
        const repeater = await this.repeater(node)
        for (const nodeR of repeater) {
          summery.push(nodeR)
        }
        // // Repeat end

      }
    }

    return summery
  }

I have been stuck here for days and really need your help. Can anyone give me a hint?

THX, John

标签: javascriptarraysmultidimensional-arrayjavascript-objectsflatten

解决方案


首先,像这样的任务实际上并不需要 async/await 或 Promise - 扁平化嵌套数据结构没有什么异步的。

由于您发布的代码不完整,因此很难使用它,因此我只是从头开始制作了一个代码示例,它将采用您的嵌套结构并返回一个扁平版本。

const flattenStructure = entries => (
  entries
  .flatMap(entry => [entry, ...flattenStructure(entry.children || [])])
  .flat()
)

如果您对上面的示例数据调用 flattenStructure(),您会看到它会生成包含在您的结构中的所有对象的列表。它不会修改对象,因此某些对象仍然具有 arrayOfObjects 属性,列出了它们的后代是什么。

该代码片段中使用的函数/概念的引用:


推荐阅读