Skip to content
Advertisement

Flatten nested JavaScript object

I have a nested object and I want to flatten/map it into a single-layered, table-like object.

[{
    a: 1,
    b: 2,
    c: [{
        x: 10,
        y: 20
    }, {
        x: 30,
        y: 40
    }]
}, {
    a: 3,
    b: 4,
    c: [{
        x: 50,
        y: 60
    }, {
        x: 70,
        y: 80
    }]
}]

From that, I want to get something like this:

[{
    a: 1,
    b: 2,
    x: 10,
    y: 20
}, {
    a: 1,
    b: 2,
    x: 30,
    y: 40
}, {
    a: 3,
    b: 4,
    x: 50,
    y: 60
}, {
    a: 3,
    b: 4,
    x: 70,
    y: 80
}]

Sure, I could simply iterate over the object with two for loops and put the result info a separate array, but I wonder, if there is a simpler solution. I already tried to play around with flatMap. It works, if I only want the c portion of my nested object, but I don’t know how to map a and b to this object.

As some of you asked for some working code, this should do it (untested):

let result = [];

for (const outer of myObj)
  for (const inner of outer.c)
    result.push({a: outer.a, b: outer.b, x: inner.x, y: inner.y});

The question is, if there is a functional one-liner or even another, better approach. In reality, my object consists of four layers and the nested for loops become messy quite fast.

Advertisement

Answer

Ideally a solution would require something to tell how far down to start classing the object as been a full object, a simple solution is just to pass the level you want. If you don’t want to pass the level, you could do a check and if none of the properties have array’s, then you would class this as a complete record, but of course that logic is something you would need to confirm.

If you want a generic version that works with multiple levels were you pass the level & using recursion you could do something like this ->

const a=[{a:1,b:2,c:[{x:10,y:20},{x:30,y:40}]},{a:3,b:4,c:[{x:50,y:60},{x:70,y:80}]}];


function flattern(a, lvl) {
  const r = [];
  function flat(a, l, o) {
    for (const aa of a) {
      o = {...o};
      for (const [k, v] of Object.entries(aa)) {
        if (Array.isArray(v) && l < lvl) flat(v, l + 1, o);
        else o[k] = v;
      }
      if (l === lvl) r.push(o);
    }
  }
  flat(a, 1);
  return r;
}

console.log(flattern(a, 2));
//console.log(flattern(a, 1));
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement