Limboer
Limboer

Reputation: 414

Recursively parse an object containing children to a key-value format object

Considering i got an object like this:

const o = {
  name: 'name1',
  age: 1,
  children: [{
    name: 'name21',
    age: 21,
    children: [{
      name: 'name31',
      age: 31,
      children: []
    }]
  }, {
    name: 'name22',
    age: 22,
    children: []
  }]
}

It has three properties, the children property could be an empty array representing it has no child. I want to transform this object to the following format:

const newObject = {
  name1_1: {
    name21_21: {
      name31_31: {}
    }, 
    name22_22: {}
  }
}

The key will be the format of name_key, and the value will be its related children, if the object has no children, the value will just be an empty object.

Here is my implementation:

const o = {
  name: 'name1',
  age: 1,
  children: [{
    name: 'name21',
    age: 21,
    children: [{
      name: 'name31',
      age: 31,
      children: []
    }]
  }, {
    name: 'name22',
    age: 22,
    children: []
  }]
}

const parser = obj => {
  const result = {}
  const { name, age } = obj
  const key = `${name}_${age}`
  if (obj.children.length > 0) {
    obj.children.forEach(child => {
      result[key] = parser(child)
    })
  } else {
    result[key] = {}
  }
  return result
}

console.log(parser(o)) // { "name1_1": { "name22_22": {} } }

I am not sure what i did wrong here, can someone help me a little bit please?

Upvotes: 1

Views: 105

Answers (3)

Scott Sauyet
Scott Sauyet

Reputation: 50807

There's already a good answer explaining what you did wrong and how to fix it. But I think you're working too hard here. Let the recursion do the heavy-lifting, and use Object.assign to glue things together. That allows for as simple an implementation as this:

const parser = ({name, age, children}) =>
  ({[`${name}_${age}`]: Object .assign ({}, ... (children || []) .map (parser))})

const o = {name: 'name1', age: 1, children: [{name: 'name21', age: 21, children: [{name: 'name31', age: 31, children: []}]}, {name: 'name22', age: 22, children: []}]}

console .log (parser (o))

Upvotes: 1

Sree.Bh
Sree.Bh

Reputation: 1789

In you implementation, result[key] = parser(child) overrides the object in second iteration to set result[key] = { name22_22: {} }. So the fix is to extend the result[key] object instead of reassignment.

const o = {
  name: 'name1',
  age: 1,
  children: [{
    name: 'name21',
    age: 21,
    children: [{
      name: 'name31',
      age: 31,
      children: []
    }]
  }, {
    name: 'name22',
    age: 22,
    children: []
  }]
}

const parser = obj => {
  const result = {}
  const {
    name,
    age
  } = obj
  const key = `${name}_${age}`
  if (obj.children.length > 0) {
    obj.children.forEach(child => {
    //  result[key] = parser(child);
      result[key] = {
        ...result[key],
        ...parser(child),
      }
    })
  } else {
    result[key] = {}
  }
  return result
}
console.log(parser(o)) // {name1_1: {name21_21: {name31_31: {}}, name22_22: {}}}

Upvotes: 1

Nenad Vracar
Nenad Vracar

Reputation: 122155

You can just assign the result of recursive calls of you function to the current object but before that you should also initialize that object if it doesn't exist.

const o = {"name":"name1","age":1,"children":[{"name":"name21","age":21,"children":[{"name":"name31","age":31,"children":[]}]},{"name":"name22","age":22,"children":[]}]}

const parser = ({ name, age, children }) => {
  const result = {}
  const key = `${name}_${age}`;

  if (!result[key]) result[key] = {}
  if (children.length) {
    children.forEach(child => {
      Object.assign(result[key], parser(child))
    })
  }

  return result;
}

console.log(parser(o))

Upvotes: 1

Related Questions