1

I have an flowchart input using jquery flowchart library like so:

Flowchart

I get the data representation as this:

{
  "operators": {
    "0": {
      "properties": {
        "title": "Start",
        "inputs": {},
        "outputs": {
          "outs": {
            "label": "Output (:i)",
            "multiple": true
          }
        },
        "class": "start-operator"
      },
      "top": 0,
      "left": 0
    },
    "1": {
      "properties": {
        "title": "End",
        "inputs": {
          "ins": {
            "label": "Input (:i)",
            "multiple": true
          }
        },
        "outputs": {},
        "class": "end-operator"
      },
      "top": null,
      "left": null
    },
    "37": {
      "properties": {
        "title": "CHROM",
        "inputs": {
          "ins": {
            "label": "Input (:i)",
            "multiple": true
          }
        },
        "outputs": {
          "output": {
            "label": "Output"
          }
        }
      },
      "left": 300,
      "top": 0
    },
    "38": {
      "properties": {
        "title": "CHROM",
        "inputs": {
          "ins": {
            "label": "Input (:i)",
            "multiple": true
          }
        },
        "outputs": {
          "output": {
            "label": "Output"
          }
        }
      },
      "left": 580,
      "top": 0
    },
    "39": {
      "properties": {
        "title": "REF",
        "inputs": {
          "ins": {
            "label": "Input (:i)",
            "multiple": true
          }
        },
        "outputs": {
          "output": {
            "label": "Output"
          }
        }
      },
      "left": 920,
      "top": 0
    },
    "40": {
      "properties": {
        "title": "REF",
        "inputs": {
          "ins": {
            "label": "Input (:i)",
            "multiple": true
          }
        },
        "outputs": {
          "output": {
            "label": "Output"
          }
        }
      },
      "left": 300,
      "top": 100
    },
    "41": {
      "properties": {
        "title": "REF",
        "inputs": {
          "ins": {
            "label": "Input (:i)",
            "multiple": true
          }
        },
        "outputs": {
          "output": {
            "label": "Output"
          }
        }
      },
      "left": 300,
      "top": 200
    },
    "42": {
      "properties": {
        "title": "REF",
        "inputs": {
          "ins": {
            "label": "Input (:i)",
            "multiple": true
          }
        },
        "outputs": {
          "output": {
            "label": "Output"
          }
        }
      },
      "left": 620,
      "top": 140
    },
    "43": {
      "properties": {
        "title": "POS",
        "inputs": {
          "ins": {
            "label": "Input (:i)",
            "multiple": true
          }
        },
        "outputs": {
          "output": {
            "label": "Output"
          }
        }
      },
      "left": 740,
      "top": 320
    }
  },
  "links": {
    "0": {
      "fromOperator": "0",
      "fromConnector": "outs",
      "fromSubConnector": 0,
      "toOperator": 37,
      "toConnector": "ins",
      "toSubConnector": 0,
      "color": " #e53935"
    },
    "1": {
      "fromOperator": "0",
      "fromConnector": "outs",
      "fromSubConnector": 1,
      "toOperator": 40,
      "toConnector": "ins",
      "toSubConnector": 0,
      "color": " #d81b60"
    },
    "2": {
      "fromOperator": "0",
      "fromConnector": "outs",
      "fromSubConnector": 2,
      "toOperator": 41,
      "toConnector": "ins",
      "toSubConnector": 0,
      "color": " #8e24aa"
    },
    "3": {
      "fromOperator": "0",
      "fromConnector": "outs",
      "fromSubConnector": 3,
      "toOperator": 43,
      "toConnector": "ins",
      "toSubConnector": 0,
      "color": " #5e35b1"
    },
    "4": {
      "fromOperator": 37,
      "fromConnector": "output",
      "fromSubConnector": 0,
      "toOperator": 38,
      "toConnector": "ins",
      "toSubConnector": 0,
      "color": " #3949ab"
    },
    "5": {
      "fromOperator": 40,
      "fromConnector": "output",
      "fromSubConnector": 0,
      "toOperator": 42,
      "toConnector": "ins",
      "toSubConnector": 0,
      "color": " #546e7a"
    },
    "6": {
      "fromOperator": 41,
      "fromConnector": "output",
      "fromSubConnector": 0,
      "toOperator": 42,
      "toConnector": "ins",
      "toSubConnector": 1,
      "color": " #039be5"
    },
    "7": {
      "fromOperator": 38,
      "fromConnector": "output",
      "fromSubConnector": 0,
      "toOperator": 39,
      "toConnector": "ins",
      "toSubConnector": 0,
      "color": " #00acc1"
    },
    "8": {
      "fromOperator": 42,
      "fromConnector": "output",
      "fromSubConnector": 0,
      "toOperator": 39,
      "toConnector": "ins",
      "toSubConnector": 1,
      "color": " #00897b"
    },
    "9": {
      "fromOperator": 39,
      "fromConnector": "output",
      "fromSubConnector": 0,
      "toOperator": "1",
      "toConnector": "ins",
      "toSubConnector": 0,
      "color": " #43a047"
    },
    "10": {
      "fromOperator": 43,
      "fromConnector": "output",
      "fromSubConnector": 0,
      "toOperator": "1",
      "toConnector": "ins",
      "toSubConnector": 1,
      "color": " #7cb342"
    }
  },
  "operatorTypes": {}
}

I want to use this for filtering data in tabulator so turn this into this:

[
  {
    "id": 1,
    "pid": null
  },
  {
    "id": 39,
    "pid": 1
  },
  {
    "id": 38,
    "pid": 39
  },
  {
    "id": 37,
    "pid": 38
  },
  {
    "id": 42,
    "pid": 39
  },
  {
    "id": 40,
    "pid": 42
  },
  {
    "id": 41,
    "pid": 42
  },
  {
    "id": 43,
    "pid": 1
  }
]

Then using this lines I turned into a tree:

const idMapping = data.reduce((acc, el, i) => {
  acc[el.id] = i;
  return acc;
}, {});

let root;
data.forEach(el => {
  // Handle the root element
  if (el.pid === null) {
    root = el;
    return;
  }
  // Use our mapping to locate the parent element in our data array
  const parentEl = data[idMapping[el.pid]];
  // Add our current el to its parent's `children` array
  parentEl.children = [...(parentEl.children || []), el];
});

Here it is as a tree:

{
  "id": 1,
  "pid": null,
  "children": [
    {
      "id": 39,
      "pid": 1,
      "children": [
        {
          "id": 38,
          "pid": 39,
          "children": [
            {
              "id": 37,
              "pid": 38
            }
          ]
        },
        {
          "id": 42,
          "pid": 39,
          "children": [
            {
              "id": 40,
              "pid": 42
            },
            {
              "id": 41,
              "pid": 42
            }
          ]
        }
      ]
    },
    {
      "id": 43,
      "pid": 1
    }
  ]
}

Hovewer I want to simplify this further to just nested arrays of the id's. Like this:

[
   1,
   [
      [
         39,
         [
            [
               38,
               [
                  37
               ],
            ],
            [
               42,
               [
                  40,
                  41
               ]
            ]
         ]
      ],
      43
   ]
]

Question is, how to convert from tree to nested array?

5
  • what is the data you have and what do you get as result? Commented Nov 5, 2020 at 19:49
  • simplify this further -- I think the nested array version is actually going to be much more complex to work with than the object. It's always ugly to work with mixed-type arrays, and here it's difficult to determine (visually or programmatically) where the node id and children are for each node. The tree you show already seems optimal to me in nearly every regard. Commented Nov 5, 2020 at 20:02
  • I agree however I am trying to convert to tabulator "Complex Filter" format tabulator.info/docs/4.8/filter Commented Nov 5, 2020 at 20:06
  • @NinaScholz I have the tree as a data and I am trying to get to the nestedd array at the end as a result. Commented Nov 5, 2020 at 20:07
  • @ggorlen Yeah you're right. I manually write it. Thanks for pointing it out. Fixed. Commented Nov 5, 2020 at 20:22

1 Answer 1

1

You can use recursion to do this; leaf ids are passed upward without an array wrapper while interior node ids are wrapped in an array with a second element for their children.

const tree = { "id": 1, "pid": null, "children": [ { "id": 39, "pid": 1, "children": [ { "id": 38, "pid": 39, "children": [ { "id": 37, "pid": 38 } ] }, { "id": 42, "pid": 39, "children": [ { "id": 40, "pid": 42 }, { "id": 41, "pid": 42 } ] } ] }, { "id": 43, "pid": 1 } ] };

const objTreeToArrTree = node => 
  node.children 
    ? [node.id].concat([node.children.map(objTreeToArrTree)])
    : node.id
;
console.log(JSON.stringify(objTreeToArrTree(tree), null, 2));

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot. Solves it beautifully.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.