Home > database >  How to flatten an object that has array of objects in Javascript
How to flatten an object that has array of objects in Javascript

Time:09-13

I am trying to solve this question it needs me to flatten this object parent that it has children each parent has 2 children, and each child has 2 children and so on....

My goal is to flatten this to one single object.

const par = {
    id: 1,
    name: "parent",
    children: [{
        id: 2,
        name: "child 1",
        children:[{
            id: 4,
            name: "child 3",
            children: [],
        },{
            id: 5,
            name: "child 4 ",
        }]
    },{
        id: 3,
        name: "child 2",
        children: [{
            id: 6,
            name: "child 5",
        },{
            id: 7,
            name: "child 6",
            children: []
        }]
    }]
}

I tried function, but it returns an array from Deep Flatten JavaScript Object Recursively

function flat(r, a) {
    let b = {};
    Object.keys(a).forEach(function (k) {
        if (k !== 'children') {
            b[k] = a[k];
        }
    });
    r.push(b);
    if (Array.isArray(a.children)) {
        b.children = a.children.map(function (a) { return a.id;});
        return a.children.reduce(flat, r);
    }
    return r;
}

CodePudding user response:

Here's an effective technique using a recursive generator flat -

function *flat({ children = [], ...t }, parentId = null) {
  yield { ...t, parentId }
  for (const child of children)
    yield *flat(child, t.id)
}

const par = {id: 1,name: "parent",children: [{id: 2,name: "child 1",children:[{id: 4,name: "child 3",children: [],},{id: 5,name: "child 4 ",}]},{id: 3,name: "child 2",children: [{id: 6,name: "child 5",},{id: 7,name: "child 6",children: []}]}]}

console.log(Array.from(flat(par)))
.as-console-wrapper { min-height: 100%; top: 0; }

You can collect all the results of a generator using Array.from -

[
  {
    "id": 1,
    "name": "parent",
    "parentId": null
  },
  {
    "id": 2,
    "name": "child 1",
    "parentId": 1
  },
  {
    "id": 4,
    "name": "child 3",
    "parentId": 2
  },
  {
    "id": 5,
    "name": "child 4 ",
    "parentId": 2
  },
  {
    "id": 3,
    "name": "child 2",
    "parentId": 1
  },
  {
    "id": 6,
    "name": "child 5",
    "parentId": 3
  },
  {
    "id": 7,
    "name": "child 6",
    "parentId": 3
  }
]

Or you can simply iterate thru the generator's result directly -

for (const flatNode of flat(par)) {
  // do something with flatNode ...
}

See this related Q&A for a technique to convert the flat tree back to a recursive tree or graph.

CodePudding user response:

You can try this

function flatTree(tree, parentId = null) {
  const { id, name, children } = tree;
  const result = [{ id, name, parentId }];
  if (Array.isArray(children)) {
    children.forEach((child) => {
      result.push(...flatTree(child, id));
    });
  }
  return result;
}

const par = {
  id: 1,
  name: "parent",
  children: [
    {
      id: 2,
      name: "child 1",
      children: [
        {
          id: 4,
          name: "child 3",
          children: [],
        },
        {
          id: 5,
          name: "child 4 ",
        },
      ],
    },
    {
      id: 3,
      name: "child 2",
      children: [
        {
          id: 6,
          name: "child 5",
        },
        {
          id: 7,
          name: "child 6",
          children: [],
        },
      ],
    },
  ],
};

console.log(flatTree(par));

/**
 * Output:
 * [
  { id: 1, name: 'parent', parentId: null },
  { id: 2, name: 'child 1', parentId: 1 },
  { id: 4, name: 'child 3', parentId: 2 },
  { id: 5, name: 'child 4 ', parentId: 2 },
  { id: 3, name: 'child 2', parentId: 1 },
  { id: 6, name: 'child 5', parentId: 3 },
  { id: 7, name: 'child 6', parentId: 3 }
]
 */

CodePudding user response:

You still owe us a description of your desired output. But if you want something as simple as this:

[
    {id: 1, name: "parent"},
    {id: 2, name: "child 1"},
    {id: 4, name: "child 3"},
    {id: 5, name: "child 4"},
    {id: 3, name: "child 2"},
    {id: 6, name: "child 5"},
    {id: 7, name: "child 6"}
]

Then a depth-first recursive function can be as simple as this:

const flatten = ({children = [], ...rest}) => [rest, ...children .flatMap (flatten)]

const par = {id: 1, name: "parent", children: [{id: 2, name: "child 1", children: [{id: 4, name: "child 3", children: []}, {id: 5, name: "child 4 ", }]}, {id: 3, name: "child 2", children: [{id: 6, name: "child 5", }, {id: 7, name: "child 6", children: []}]}]}

console .log (flatten (par))
.as-console-wrapper {max-height: 100% !important; top: 0}

If you wanted to include a parentId field, using null for root-level objects, it's only slightly more complex:

const flatten = ({id, children = [], ...rest}, parentId = null) => [
  {id, ...rest, parentId}, ...children .flatMap (c => flatten(c, id))
]
  • Related