1

As per my original question geared specifically for React (React recursive tree pass JSON path), I have realised the problem is pretty generic.

I have a recursive function that essentially loops through a treelike JSON structure, each time it outputs a branch I want to pass an object of the structures location in the tree like below.. Is there a simpler way to pass the structure? Is the data structure poor / should each chid have a unique ID attached?

My JSON object is below so you can see what I'm working with.

Any help much appreciated!

Level 1 child

{value: "Fruit"}

Level 2 child

{value: "Fruit", nested_values: [{ value: 'Tropical'}] }

Level 3 child

{value: "Fruit", nested_values: [{ value: 'Tropical', nested_values:[{ value: 'Pineapple' }]}] }

Code - kind of works, but then I get all values within the same nested_values array

 const createSelectionHierarchy = (data, isSub, level = 2, hierarchy = {}) => {
        let children = [];
        if (isSub) { level++; }
        let obj = {};
        obj.name = cat;

        const cat = hierarchy.value;    

        for (let i in data) {

            const subcat = data[i].value;

            if (typeof(data[i].nested_values) === 'object') { // Sub array found, build structure
                obj.values = subcat;
                obj.nested_values = [];

                hierarchy.nested_values.push(obj);

                children.push(
                    <FilterItem key={i} data={data[i]} hierarchy={hierarchy} level={level}>
                        {createSelectionHierarchy(data[i].nested_values, true, level, hierarchy)}
                    </FilterItem>
                );
            } else { // No sub array, bottom of current branch
                children.push(
                    <p className="filter-item level-last" key={i}>
                        {data[i].value}
                    </p>);
            }
        }
        return children;
    }

JSON

{
        "value": "Fruit",
        "occurrence_count": 5,
        "nested_values": [{
            "value": "Berries",
            "occurrence_count": 3,
            "nested_values": [{
                "value": "Strawberry",
                "occurrence_count": 1
            }, {
                "value": "Blackberry",
                "occurrence_count": 1
            }, {
                "value": "Raspberry",
                "occurrence_count": 1
            }, {
                "value": "Redcurrant",
                "occurrence_count": 1
            }, {
                "value": "Blackcurrant",
                "occurrence_count": 1
            }, {
                "value": "Gooseberry",
                "occurrence_count": 1
            }, {
                "value": "Cranberry",
                "occurrence_count": 1
            }, {
                "value": "Whitecurrant",
                "occurrence_count": 1
            }, {
                "value": "Loganberry",
                "occurrence_count": 1
            }, {
                "value": "Strawberry",
                "occurrence_count": 1
            }]
        }, {
            "value": "Tropical",
            "occurrence_count": 2,
            "nested_values": [{
                "value": "Pineapple",
                "occurrence_count": 1
            }, {
                "value": "Mango",
                "occurrence_count": 1
            }, {
                "value": "Guava",
                "occurrence_count": 1
            }, {
                "value": "Passion Fruit",
                "occurrence_count": 1
            }, {
                "value": "Dragon Fruit",
                "occurrence_count": 1
            }]
        }]
}

Desired output

<FilterItem ...... hierarchy={{value: "Fruit"}}>
    <FilterItem ...... hierarchy={{value: "Fruit", nested_values: [{ value: 'Tropical'}] }}>
        <FilterItem ...... hierarchy={{value: "Fruit", nested_values: [{ value: 'Tropical', nested_values:[{ value: 'Pineapple' }]}] }}>
        </FilterItem>
    </FilterItem>
</FilterItem>
7
  • @r1verside - do you have an example? Commented Feb 13, 2017 at 21:33
  • @ibrahimmahrir - I updated my answer Commented Feb 13, 2017 at 21:49
  • Do you have a JavaScript (meaning ECMA Script) version of the code? Commented Feb 13, 2017 at 22:05
  • @Traktor53 - unfortunately not, but the above is pretty easy to decipher? It's just a function, the only wierd bit is i'm pushing JSX elements into an array instead of an object Commented Feb 13, 2017 at 22:07
  • @Zinc Please take a look at my answer to see if that's what you're after. I'll add an explanation if so. Commented Feb 13, 2017 at 22:16

1 Answer 1

2

For each branch (level of tree), this function will extract the value and then call itself on each of its children, if there are any, and store their return values in an array.

function convert(branch) {  
  const hierarchy = {
    value: branch.value
  };
  if (branch.nested_values !== undefined)
    hierarchy.nested_values = branch.nested_values.map(subranch => convert(subranch))
  return hierarchy;
}

const input = {
  "value": "Fruit",
  "occurrence_count": 5,
  "nested_values": [{
    "value": "Berries",
    "occurrence_count": 3,
    "nested_values": [{
      "value": "Strawberry",
      "occurrence_count": 1
    }, {
      "value": "Blackberry",
      "occurrence_count": 1
    }, {
      "value": "Raspberry",
      "occurrence_count": 1
    }, {
      "value": "Redcurrant",
      "occurrence_count": 1
    }, {
      "value": "Blackcurrant",
      "occurrence_count": 1
    }, {
      "value": "Gooseberry",
      "occurrence_count": 1
    }, {
      "value": "Cranberry",
      "occurrence_count": 1
    }, {
      "value": "Whitecurrant",
      "occurrence_count": 1
    }, {
      "value": "Loganberry",
      "occurrence_count": 1
    }, {
      "value": "Strawberry",
      "occurrence_count": 1
    }]
  }, {
    "value": "Tropical",
    "occurrence_count": 2,
    "nested_values": [{
      "value": "Pineapple",
      "occurrence_count": 1
    }, {
      "value": "Mango",
      "occurrence_count": 1
    }, {
      "value": "Guava",
      "occurrence_count": 1
    }, {
      "value": "Passion Fruit",
      "occurrence_count": 1
    }, {
      "value": "Dragon Fruit",
      "occurrence_count": 1
    }]
  }]
};

function convert(branch) {
  const hierarchy = {
    value: branch.value
  };
  if (branch.nested_values !== undefined)
    hierarchy.nested_values = branch.nested_values.map(subranch => convert(subranch))
  return hierarchy;
}

console.log(convert(input));

On a side note, what you supplied is not valid JSON (keys mustn't have quotes), it is a JavaScript object. To get an object from a JSON string, you have to call JSON.parse().

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

3 Comments

Thanks for this, but I think you took my problem too literally, I'm just looking for the hierarchy object to have a new array structure pushed into it on each iteration. i.e. hierarchy={{value: "Fruit"}}, then hierarchy={{value: "Fruit", nested_values: [{ value: 'Tropical'}] }} etc
I guess I did. What you're after is even simpler - see the edit.
Cool, how would I work this into my recursive function above?

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.