JeanCHilger
JeanCHilger

Reputation: 446

javascript replace property name in n-ary tree object

Supose I have a n-ary tree structure (in json) like this:

[
  {
    "text": "Some title",
    "children": [
      {
        "text": "Some title",
        "children": [
          ...
        ]
      },
      ...  
    ]
  }
]

Where I neither know how many children the nodes will have nor the tree's depth.

What I would like to do is change the name of property text to name, across all children.

I've tryed this, with a recursive function func:

func(tree) {
  if (!tree) return;

  for (let node of tree) {
    node.name = node.text
    delete node.text;
    
    return func(node.children);
  }
}

But it didn't work. How would I do that?

Upvotes: 5

Views: 726

Answers (2)

Yevhen Horbunkov
Yevhen Horbunkov

Reputation: 15530

I would say, the main problem with your code is that node variable holds the value of corresponding array items and it doesn't keep the reference to those items themselves, so, basically, mutations you attempt to make are never applied to original array (but only to temporary variable reassigned upon each loop iteration)

If you prefer to mutate original array and feel comfortable using for(-loops for that purpose, you'd be much better off using for(..in-loop to access array items by their keys:

const src = [
  {
    text: "Some title",
    children: [
      {
        text: "Some title",
        children: []
      },
    ]
  }
],

    func = tree => {
      for(const nodeIdx in tree){
        const {text:name, children} = tree[nodeIdx]
        func(children)
        tree[nodeIdx] = {name, children}
      }
    }
    
func(src)

console.log(src)
.as-console-wrapper{min-height:100%;}

However, I would avoid mutating source data and return new array instead (e.g. with Array.prototype.map():

const src = [
  {
    text: "Some title",
    children: [
      {
        text: "Some title",
        children: []
      },
    ]
  }
],

      func = tree => 
        tree.map(({text:name,children}) => ({
          name, 
          ...(children && {children: func(children)})
        }))


console.log(func(src))
.as-console-wrapper{min-height:100%;}

Upvotes: 3

jchung201
jchung201

Reputation: 71

You would use the in operator here.

for (let node **in** tree) {
  node.name = node.text
  delete node.text;

    
  return func(node.children);
}

Upvotes: 1

Related Questions