使用 Javascript ECMAScript 6 将 table 数据转换为分层树数据的算法

Algorithm to convert a table data to hierarchical tree data using Javascript ECMAScript 6

我有一个 JSON table 数据,想要转换为 JSON 树数据,如下所示。我正在 JavaScript 中使用任何新的 ECMAScript 6 运算符或具有功能方法的语句(不是通过 ES5 的标准递归算法)寻找一种有效的算法?

Table数据:

[
   {
      "Children":"4th Grand Father"
   },
   {
      "Name":"4th Grand Father",
      "Children":"3rd Grand Father"
   },
   {
      "Name":"3rd Grand Father",
      "Children":"2nd Grand Father"
   },
   {
      "Name":"2nd Grand Father",
      "Children":"Grand Father"
   },
   {
      "Name":"Grand Father",
      "Children":"Father"
   },
   {
      "Name":"Grand Father",
      "Children":"Uncle"
   },
   {
      "Name":"Uncle",
      "Children":"Cousin"
   },
   {
      "Name":"Father",
      "Children":"Brother"
   },
   {
      "Name":"Father",
      "Children":"Me"
   }
]

树数据:

[
  {
    "Name": "4th Grand Father",
    "Children": [
      {
        "Name": "3rd Grand Father",
        "Children": [
          {
            "Name": "2nd Grand Father",
            "Children": [
              {
                "Name": "Grand Father",
                "Children": [
                  {
                    "Name": "Father",
                    "children": [
                      {
                        "Name": "Brother"
                      },
                      {
                        "Name": "Me"
                      }
                    ]
                  },
                  {
                    "Name": "Uncle",
                    "children": [
                      {
                        "Name": "Cousin"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
]

您可以使用这个 ES6 函数,它使用 Map、箭头函数、解构参数赋值。您甚至可以用扩展语法替换 concat 调用,但我认为这不会带来任何好处:

const makeTree = (data) => {
    const hash = data.reduce ( (acc, {Name, Children}) => 
        acc.set(Name, (acc.get(Name) || []).concat(Children)) 
    , new Map );

    const recurse = (Name) => hash.has(Name)
            ?   { Name, Children: hash.get(Name).map(recurse) }
            :   { Name };
    return recurse(undefined).Children;
}

// Sample data
const data = [
   {
      "Children":"4th Grand Father"
   },
   {
      "Name":"4th Grand Father",
      "Children":"3rd Grand Father"
   },
   {
      "Name":"3rd Grand Father",
      "Children":"2nd Grand Father"
   },
   {
      "Name":"2nd Grand Father",
      "Children":"Grand Father"
   },
   {
      "Name":"Grand Father",
      "Children":"Father"
   },
   {
      "Name":"Grand Father",
      "Children":"Uncle"
   },
   {
      "Name":"Uncle",
      "Children":"Cousin"
   },
   {
      "Name":"Father",
      "Children":"Brother"
   },
   {
      "Name":"Father",
      "Children":"Me"
   }
];

const result = makeTree(data);

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

解释:

hash 变量是从一个空的 Map 构建的,向其中添加由 Name 键入的记录。链接到每个键的值是 children 信息,作为一个数组。当遇到相同的 Name 时(即 acc.get(Name) returns something),将 child 添加到已经存在的数组中,否则 (|| []) 创建一个空数组,并向其中添加 child。

一旦 hash 完成,层次结构的顶部由其缺失的 Name (undefined) 占据,并通过递归 children 在 hash 中查找并添加到最终的 object.

因为结果 object 是一个 object 和一个 Children 数组,而期望的结果实际上就是那个数组,它是返回的 Children 属性。