【问题标题】:How to Convert this Function to Recursive Function如何将此函数转换为递归函数
【发布时间】:2020-09-03 21:52:26
【问题描述】:

我正在尝试将 JSON 转换为对象数组。

到目前为止,我有这个工作代码,其中 params data 是 JSON。如果存在properties 键,它可以是深度嵌套的。

因此,在下面的代码中,如果存在properties 键,则对其进行循环并构建一个对象数组。

将其转换为递归函数的好方法是什么。到目前为止,我微弱的尝试非常缺乏光泽。

const rec = (data: Object) => {
  let obj1;
  for (const k in data) {
    obj1 = this.buildPropertyObj(data, k);
    if (data[k].properties) {
      let obj2;
      obj1.items = [];
      for (const j in data[k].properties) {
        obj2 = this.buildPropertyObj(data[k].properties, j);
        if (data[k].properties[j].properties) {
          obj2.items = [];
          for (const i in data[k].properties[j].properties) {
            obj2.items.push(this.buildPropertyObj(data[k].properties[j].properties, i));
          }
        }
        obj1.items.push(obj2)
      }
    }
  }
  items.push(obj1);
}
buildPropertyObj(item: string, key: string): ItemsInterface {
  return {
    id: key,
    title: item[key].title,
    description: item[key].description
  };
}

例如,我编写了这个递归函数,它将 JSON 的精确副本复制到对象数组中,但它不保留嵌套,它只是一个平面数组。我一直在尝试写一些干净的东西来保持嵌套,但到目前为止还没有运气...... :(

buildForm(): JsonFormInterface {
  const listItems: any = [];
  const recursiveBuild = (items: any, listItems: Array<any>): void => {
    for (const key in items) {
      listItems.push(this.buildPropertyObj(items, key));
      recursiveBuild(items[key].properties, listItems);
    }
  };
  recursiveBuild(this.formSchema.properties, listItems);

  return { title: this.formSchema.title, items: listItems };
}

JSON:

{
  "group_container1": {
    "type": "object",
    "title": "Container 1 Group",
    "description": "Awesome description here.",
    "properties": {
      "group_1": {
        "type": "object",
        "title": "Container 1 Group 1",
        "description": "Awesome description here.",
        "properties": {
          "C_1_G_1_Item_1": {
            "title": "Container 1 Group 1 Item 1",
            "description": "This is a select box",
            "type": "string",
            "enum": ["Option 1a", "Option 2b"]
          },
          "C_1_G_1_Item_2": {
            "title": "Container 1 Group 1 Item 2",
            "description": "This is a select box",
            "type": "string",
            "enum": []
          },
          "C_1_G_1_Item_3": {
            "title": "Container 1 Group 1 Item 3",
            "description": "This is a select box",
            "type": "string",
            "enum": [],
            "properties": {
              "boom": {
                "title": "Boom !",
                "description": "This is a select box",
                "type": "string",
                "properties": {
                  "bam": {
                    "title": "Bam !",
                    "description": "This is a select box",
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

想要的结果:

{
  "title": "Container 1 Group",
  "description": "Awesome description here.",
  "items": [
    {
      "id": "group_1",
      "title": "Container 1 Group 1",
      "description": "Awesome description here.",
      "items": [
        {
          "id": "C_1_G_1_Item_1",
          "title": "Container 1 Group 1 Item 1",
          "description": "This is a select box",
        },
        {
          "id": "C_1_G_1_Item_2",
          "title": "Container 1 Group 1 Item 2",
          "description": "This is a select box",
        },
        {
          "id": "C_1_G_1_Item_3",
          "title": "Container 1 Group 1 Item 3",
          "description": "This is a select box",
          "items": [
            {
              "id": "boom",
              "title": "Boom !",
              "description": "This is a select box",
              "items": [
                {
                  "id": "bam",
                  "title": "Bam !",
                  "description": "This is a select box",
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

【问题讨论】:

  • 你能分享一个输入和预期输出的例子吗?
  • 你有一小部分数据和想要的结果吗?
  • 我已经添加了一些示例数据和最终结果,感谢您的时间。
  • recursiveBuild 函数应该自己创建输出对象/数组,而不是将数据附加到同一个顶层

标签: javascript typescript algorithm recursion data-structures


【解决方案1】:

在纯 Javascript 中,您可以通过查看对象中的键和值以及嵌套 properties 的映射来采用递归方法。

const
    convert = object => Object
        .values(object)
        .map(({ title, description, properties }) => ({
            title,
            description,
            ...(properties
                ? { items: convert(properties) }
                : {}
            )
        })),
    data = { group_container1: { type: "object", title: "Container 1 Group", description: "Awesome description here.", properties: { group_1: { type: "object", title: "Container 1 Group 1", description: "Awesome description here.", properties: { C_1_G_1_Item_1: { title: "Container 1 Group 1 Item 1", description: "This is a select box", type: "string", enum: ["Option 1a", "Option 2b"] }, C_1_G_1_Item_2: { title: "Container 1 Group 1 Item 2", description: "This is a select box", type: "string", enum: [] }, C_1_G_1_Item_3: { title: "Container 1 Group 1 Item 3", description: "This is a select box", type: "string", enum: [], properties: { boom: { title: "Boom !", description: "This is a select box", type: "string", properties: { bam: { title: "Bam !", description: "This is a select box", type: "string" } } } } } } } } } },
    result = convert(data);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 谢谢,理解缩进有点麻烦。另外我在{ description, properties } - Property 'description' does not exist on type '{}' 上收到类型错误,可能有一个额外的逗号,还是我看错了?
  • 你指的是哪个逗号?
  • 这分隔变量。
  • 很棒,它似乎有效,我花了一段时间才理解缩进。
  • 你可以使用一个函数来获取解构变量和一个新对象。或者把不需要的东西拿出来,把剩下的拿走Rest in Object Destructuring ...
【解决方案2】:

采用 Nina Scholz 的 非常正确的答案并稍微调整一下,使其包含 key 值以创建 id 属性。还添加缩进和 TypeScript 类型。

const recursiveBuild = (data: any): Array<ItemsInterface> => {
  return Object
    .entries(data)
    .map(([key, { properties }]: any, index, item) => {
      const propObj = this.buildPropertyObj(item[index][1], key);
      return {
          ... propObj,
          ...(properties ? { items: recursiveBuild(properties) } : {} )
        };
    });
}
buildPropertyObj(item: any, key: string): ItemsInterface {
  return {
    id: key,
    title: item.title,
    description: item.description,
  };
}

谢谢大家。

【讨论】:

    猜你喜欢
    • 2021-11-03
    • 2020-08-20
    • 1970-01-01
    • 2021-07-06
    • 2014-03-01
    • 2020-05-08
    • 2016-01-06
    相关资源
    最近更新 更多