Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Turn a 2D Array into a tree

Tags:

javascript

I am working with Google Apps Script and I can retrieve the Google Spreadsheet Data as 2D array. I want to convert this array into a tree representation to build a folder hierarchy in Google Drive. enter image description here

Here is the 2D Array which I can get from Google Spreadsheet.

var data =  [
       ["F1", "F1S1","",""],
       ["", "F1S2", "F1S2S1", ""],
       ["", "", "F1S2S2", ""],
       ["", "F1S3", "", ""],
       ["F2", "F2S1", "", ""],
       ["", "F2S2", "F2S2S1", ""],
       ["", "", "F2S2S2", "F2S2S2S1"],
       ["", "", "", "F2S2S2S2"]
    ]

Now I am trying to turn it as below JSON.

[
    {
        "name" : "F1",
        "children" : [
            {
                "name" : "F1S1"
            },
            {
                "name" : "F1S2",
                "children" : [
                    {
                        "name" : "F1S2S1"
                    },
                    {
                        "name" : "F1S2S2"
                    }
                ]
            },
            {
                "name" : "F1S3"
            }
        ]
    },
    {
        "name" : "F2",
        "children" : [
            {
                "name" : "F2S1"
            },
            {
                "name" : "F2S2",
                "children" : [
                    {
                        "name" : "F2S2S1"
                    },
                    {
                        "name" : "F2S2S2",
                        "children" : [
                            {
                                "name" : "F2S2S2S1"
                            },
                            {
                                "name" : "F2S2S2S2"
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

I have tried to use array.reduce method but not able to deduce proper logic. Could Someone guide me.

var data = [
  ["F1", "F1S1", "", ""],
  ["", "F1S2", "F1S2S1", ""],
  ["", "", "F1S2S2", ""],
  ["", "F1S3", "", ""],
  ["F2", "F2S1", "", ""],
  ["", "F2S2", "F2S2S1", ""],
  ["", "", "F2S2S2", "F2S2S2S1"],
  ["", "", "", "F2S2S2S2"]
]

var tree = data.reduce(function(tree, item) {
  var tempTree = tree;
  for (var i = 0; i < item.length; i++) {
    if (!tempTree[item[i]])
      tempTree[item[i]] = {};
    tempTree = tempTree[item[i]];
  }
  return tree;
}, {});

console.log(tree)
like image 470
Waqar Ahmad Avatar asked Feb 11 '19 11:02

Waqar Ahmad


People also ask

How do you convert a 2d array to a tree?

Start by creating an n x n array of nodes and assign the numbers to the nodes. This array will contain the leaves of the tree. Then create a new two dimensional array of nodes with dimensions n/2 * n/2. For each node, assign the respective nodes of the original array as children.


Video Answer


1 Answers

With sorted data, you could take a helper array for keeping the last levels of the inserted nodes.

var data = [["F1", "F1S1", "", ""], ["", "F1S2", "F1S2S1", ""], ["", "", "F1S2S2", ""], ["", "F1S3", "", ""], ["F2", "F2S1", "", ""], ["", "F2S2", "F2S2S1", ""], ["", "", "F2S2S2", "F2S2S2S1"], ["", "", "", "F2S2S2S2"]],
    result = [],
    levels = [result];

data.forEach(a =>
    a.forEach((name, i) => {
        if (!name) return;
        levels[i].push({ name, children: (levels[i + 1] = []) });
    })
);
  
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

If you do not like to have empty children, you could check in advance and add the children before adding a new node.

var data = [["F1", "F1S1", "", ""], ["", "F1S2", "F1S2S1", ""], ["", "", "F1S2S2", ""], ["", "F1S3", "", ""], ["F2", "F2S1", "", ""], ["", "F2S2", "F2S2S1", ""], ["", "", "F2S2S2", "F2S2S2S1"], ["", "", "", "F2S2S2S2"]],
    result = [],
    levels = [result];

data.forEach(a =>
    a.forEach((name, i) => {
        if (!name) return;
        if (i && !levels[i - 1][levels[i - 1].length - 1].children) {
            levels[i] = [];
            levels[i - 1][levels[i - 1].length - 1].children = levels[i];
        }
        levels[i].push({ name });
    })
);
  
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 57
Nina Scholz Avatar answered Oct 21 '22 23:10

Nina Scholz