Ryan Zeelie
Ryan Zeelie

Reputation: 1510

Recursively create a parent and child string for every child and it's child

I'm attempting to create an array of objects as the final output which includes the parent name and it's children. The id would be the last child in the name

Sample output I'm trying to achieve :

[
{id:1,name:"1"},
{id:2,name:"1-2"},
{id:3,name:"1-2-3"},
{id:4,name:"1-2-4"}
]

Code:

let item = {
  id: 1,
  name: "1",
  children: [{
    id: 2,
    name: "2",
    children: [{
        id: 3,
        name: "3",
        children: []
      },
      {
        id: 4,
        name: "4",
        children: []
      }
    ]
  }]
}


const createList = (item) => {

  let name = item.children.map(e => {
    return createList(e)
  })
  return item.name + "-" + name
}

console.log(createList(item))

Upvotes: 2

Views: 76

Answers (3)

Scott Sauyet
Scott Sauyet

Reputation: 50797

I think we can do this more simply. I'd prefer code like this:

const convert = ({id, name, children}, prefix = '') => [
  {id, name: prefix + name},
  ...children .flatMap (c => convert (c, prefix + name + '-'))
]

const sample = {id: 1, name: "1", children: [{id: 2, name: "2", children: [{id: 3, name: "3", children: []}, {id: 4, name: "4", children: []}]}]}
  
console .log (convert (sample))
.as-console-wrapper {max-height: 100% !important; top: 0}

Note that our recursion bottoms without an explicit case for it because mapping over an empty array returns an empty array, without making further calls. And that result is just folded into our accumulation by flatMap.

If you prefer not to include default parameters (and there are some good reasons for that preference), you could simply wrap an internal version of this function into a public function, supplying the initial prefix value to that internal one. This would also allow us to simplify the function reference passed to flatMap:

const _convert = (prefix = '') => ({id, name, children}) => [
  {id, name: prefix + name},
  ...children .flatMap (_convert (prefix + name + '-'))
]

const convert = _convert ('')

const sample = {id: 1, name: "1", children: [{id: 2, name: "2", children: [{id: 3, name: "3", children: []}, {id: 4, name: "4", children: []}]}]}
  
console .log (convert (sample))
.as-console-wrapper {max-height: 100% !important; top: 0}

Upvotes: 0

Damzaky
Damzaky

Reputation: 10826

A simple recursion will do the trick:

let item = {
  id: 1,
  name: "1",
  children: [{
    id: 2,
    name: "2",
    children: [{
        id: 3,
        name: "3",
        children: []
      },
      {
        id: 4,
        name: "4",
        children: []
      }
    ]
  }]
}

var result = []


const createList = (items, acc) => {
  items.forEach(item => {
    const newAcc = {
      id: item.id,
      name: acc ? `${acc.name}-${item.name}` : `${item.name}`
    }
    result.push(newAcc)
    createList(item.children, newAcc)
  })
}

createList([item], null)

console.log(result)

Upvotes: 3

user1689537
user1689537

Reputation: 21

You're on the right track with recursion, but the map function is probably not the best choice for this. Map function doesn't work the way you might expect when there is only one element in the array, as it is not meant to be used to process lists in such a way, but only to "map" data.

Try switching to a for loop or foreach and building the string yourself.

Example:

let sample = {
  id: 1,
  name: "1",
  children: [{
    id: 2,
    name: "2",
    children: [{
        id: 3,
        name: "3",
        children: []
      },
      {
        id: 4,
        name: "4",
        children: []
      }
    ]
  }]
};

function buildArray(input, parentName) {
  let output = [];

  for (let item of input) {
    let name = parentName ? `${parentName}-${item.name}` : item.name;
    output.push({ id: item.id, name: name });
    if (item.children) {
      output = output.concat(buildArray(item.children, name));
    }
  }

  return output;
}

let result = buildArray(sample.children, sample.name);

let output = document.getElementById('myresult');
output.innerText = JSON.stringify(result);
<p id="myresult"></p>

Upvotes: 2

Related Questions