Algorithm for Transforming Data Structures in Tree Plugin Displays

Published: 2017-06-03

Problem Background

In scenarios that display directory structures, organizational hierarchies, and similar layouts, we often use mature tree plugins for easy presentation, such as zTree. Most plugins support parsing two kinds of data source formats: a common two-dimensional (flat) data structure and a tree (hierarchical) data structure. The naming for these two structures may vary across plugins; here I will refer to them as two-dimensional structure and tree structure. Examples are shown below:

// Two-dimensional data structure
[{
  "id": "001",
  "name": "Headquarters",
  "parentId": "0"
}, {
  "id": "002",
  "name": "Secondary Store 1",
  "parentId": "001"
}, {
  "id": "003",
  "name": "Tertiary Store",
  "parentId": "002"
}, {
  "id": "004",
  "name": "Secondary Store 2",
  "parentId": "001"
}]

// Tree data structure
[{
    "id": "001",
    "name": "Headquarters",
    "parentId": "0",
    "children": [{
      "id": "002",
      "name": "Secondary Store 1",
      "parentId": "001",
      "children": [{
        "id": "003",
        "name": "Tertiary Store",
        "parentId": "002",
        "children": []
      }]
    }, {
      "id": "004",
      "name": "Secondary Store 2",
      "parentId": "001",
      "children": []
    }]
}]

However, in some plugins or special scenarios, we need to convert between these two data structures and must write a helper function to do so. Below I provide two utility functions to perform the conversions.

Note: It should be noted that the utility functions have not been tested with very large data volumes, so if you need real-time or large-scale source data conversion, please test and analyze them yourself and consider preprocessing or asynchronous approaches. Due to limitations in my technical ability, there is room for algorithmic performance optimization; if you have a better approach, please share — thanks!

Solution

I will introduce the conversion algorithms between the two data structures separately. For each section I will first paste the full function code for easy copy-paste, then briefly explain the general logic.

Two-dimensional structure => Tree structure

This function can be tested by callinglistToTree("0", "parentId", "id", sourceData)to invoke it,sourceDatarefers to the two-dimensional data example given at the start of the article.

Below is a brief explanation of the logic. Line 10 does a basic validation of the input parameters, then declares two variables rootList and nodeList. rootList contains top-level root nodes, and nodeList holds the remaining child nodes. The loop from lines 14 to 20 assigns values to those two variables. After that, the code further validates the data based on those variables. Once validated, it calls the internal function childrenNodeAdd, which is recursively invoked to add a child array named "children" to each node. The two arguments are rootNodeList and childrenList, representing the parent node set and all subsequent child nodes. On the first call at line 23, the top-level roots and all their descendants are passed in. Below is the annotated code snippet:

Tree structure => Two-dimensional structure

This function can be tested by callingtreeToList("children", sourceData)to invoke it,sourceDatarefers to the tree-structure example given at the beginning of the article. The logic here is straightforward and will not be repeated.

Last updated