Search code examples
javascriptarraystypescriptecmascript-5

Reverse Traverse a hierarchy


I have a hierarchy of objects that contain the parent ID on them. I am adding the parentId to the child object as I parse the json object like this.

public static fromJson(json: any): Ancestry | Ancestry[] {
    if (Array.isArray(json)) {
      return  json.map(Ancestry.fromJson) as Ancestry[];
    }

    const result = new Ancestry();
    const { parents } = json;

    parents.forEach(parent => {
      parent.parentId = json.id;
    });

    json.parents = Parent.fromJson(parents);
    Object.assign(result, json);
    return result;
  }

Any thoughts on how to pull out the ancestors if I have a grandchild.id?

The data is on mockaroo curl (Ancestries.json)

As an example, with the following json and a grandchild.id = 5, I would create and array with the follow IDs

['5', '0723', '133', '1']

[{
  "id": "1",
  "name": "Deer, spotted",
  "parents": [
    {
      "id": "133",
      "name": "Jaime Coldrick",
      "children": [
        {
          "id": "0723",
          "name": "Ardys Kurten",
          "grandchildren": [
            {
              "id": "384",
              "name": "Madelle Bauman"
            },
            {
              "id": "0576",
              "name": "Pincas Maas"
            },
            {
              "id": "5",
              "name": "Corrie Beacock"
            }
          ]
        },

Solution

  • There is perhaps very many ways to solve this, but in my opinion the easiest way is to simply do a search in the data structure and store the IDs in inverse order of when you find them. This way the output is what you are after.

    You could also just reverse the ordering of a different approach.

    I would like to note that the json-structure is a bit weird. I would have expected it to simply have nested children arrays, and not have them renamed parent, children, and grandchildren.

    let data = [{
      "id": "1",
      "name": "Deer, spotted",
      "parents": [
        {
          "id": "133",
          "name": "Jaime Coldrick",
          "children": [
            {
              "id": "0723",
              "name": "Ardys Kurten",
              "grandchildren": [
                {
                  "id": "384",
                  "name": "Madelle Bauman"
                },
                {
                  "id": "0576",
                  "name": "Pincas Maas"
                },
                {
                  "id": "5",
                  "name": "Corrie Beacock"
                }
              ]
            }]
        }]
    }]
    
    const expectedResults =  ['5', '0723', '133', '1']
    
    function traverseInverseResults(inputId, childArray) {
        if(!childArray){ return }
        for (const parent of childArray) {
            if(parent.id === inputId){
                return [parent.id]
            } else {
                let res = traverseInverseResults(inputId, parent.parents || parent.children || parent.grandchildren) // This part is a bit hacky, simply to accommodate the strange JSON structure.
                if(res) {
                    res.push(parent.id)
                    return res
                }
            }
        }
        return
    }
    let result = traverseInverseResults('5', data)
    console.log('results', result)
    console.log('Got expected results?', expectedResults.length === result.length && expectedResults.every(function(value, index) { return value === result[index]}))