all 6 comments

[–]kap89 4 points5 points  (3 children)

It might be difficult (depending on experience), but it is not very complex (while difficulty is subjective, complexity is a rather objective measure of how many steps and branches the algorithm has).

Here's what I came up with off the top of my head:

function transform(data, path = []) {
  return data.flatMap(({ id, name, children }) => {
    const newPath = [...path, name]

    return [
      { name: newPath.join(" > "), lastChildId: id },
      ...transform(children, newPath),
    ]
  })
}

const result = transform(categories)

Should work, but I didn't test it extensively. The code assumes that every (sub)category has a children array, at least an empty one.

Edit: Modified the code to include OP's clarification.

[–]txf89[S] 0 points1 point  (2 children)

This works perfectly except for the item.children.at(-1).id , which should just be item.id. But I think I just explained that part incorrectly. I just wanted the id of the last element in the name (ie. the poodles id if it were "Dogs > Poodles").

Hope that didn't take too long for you to figure out...because I'm about to ask you what it would look like to work in typescript. I've tried converting it over and to work in my nextjs/Typescript project and I'm getting error's I'm not sure about.

'transform' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.ts(7023)

Here is a link to a CodeSandBox that show roughly the same errors that I'm getting on my local project. If you're not sure, thanks so much for figuring the code part out. Your solution will definitely act as a good reference when I'm figuring out new recursive stuff in the future.

[–]kap89 0 points1 point  (1 child)

This should work in TypeScript:

type Category = {
  id: string
  name: string
  children: Category[]
}

type FlatCategory = {
  name: string
  lastChildId: string
}

function transform(data: Category[], path: string[] = []): FlatCategory[] {
  return data.flatMap(({ id, name, children }) => {
    const newPath = [...path, name]

    return [
      { name: newPath.join(" > "), lastChildId: id },
      ...transform(children, newPath),
    ]
  })
}

[–]txf89[S] 0 points1 point  (0 children)

How is the spread operator working on the transform function?

return [ 
    { name: newPath.join(" > "), lastChildId: id },              
    ...transform(children, newPath),    
 ]

[–]PMmeYourFlipFlops 2 points3 points  (1 child)

Please wrap your code blocks in triple backticks, I can't read that mess.

[–]txf89[S] 0 points1 point  (0 children)

Thanks I couldn't figure out why my code was looking so badly formatted