Home > Mobile >  Grouping nested object properties
Grouping nested object properties

Time:08-20

I have this nested Object:

{
  1: { one: { a: 5, b: 6, c: 7, d: 8 } },
  2: { one: { a: 6, b: 9, c: 10, d: 12, e: 1 } },
  3: { one: { a: 3, b: 4, c: 9 } },
}

Required output:

{
  one: {
    a: [5, 6, 3]
    b: [6, 9, 4]
    c: [7, 10, 9]
    d: [12]
    e: [1]
  }
}

Tried nested queries but failed.

CodePudding user response:

Here's my take. A series of nested for for...in loops. Tried to optimize for readability.

const object = {
  1: { one: { a: 5, b: 6, c: 7, d: 8 } },
  2: { one: { a: 6, b: 9, c: 10, d: 12, e: 1 } },
  3: { one: { a: 3, b: 4, c: 9 } },
};

const result = {};

for (const group in object) {
  for (const num in object[group]) {
    if (!result[num]) {
      result[num] = {};
    }
    for (const letter in object[group][num]) {
      if (!result[num][letter]) {
        result[num][letter] = [];
      }
      result[num][letter].push(object[group][num][letter])
    }
  }
}

console.log(result)

CodePudding user response:

Use nested loops. You don't care about the keys of the top-level object, so loop over its values with Object.values(). Then loop over the keys and values of the nested objects. Create nested objects in the result when needed, then add the values.

const obj1 = { 
  1: {one:{ a:5,b:6,c:7,d:8}},
  2: {one:{ a:6,b:9,c:10,d:12,e:1}},
  3: {one:{a:3,b:4,c:9}}
};

let result = {};
Object.values(obj1).forEach(val1 => {
  Object.entries(val1).forEach(([key2, val2]) => {
    if (!result.hasOwnProperty(key2)) {
      result[key2] = {};
    }
    res2 = result[key2];
    Object.entries(val2).forEach(([key3, val3]) => {
      if (!res2.hasOwnProperty(key3)) {
        res2[key3] = [val3];
      } else {
        res2[key3].push(val3);
      }
    });
  });
});

console.log(result);

CodePudding user response:

My approach is doing two groups:

  • group the first top-level object keys and get their values store them as value of an array.
  • group the keys of the arrays value (in the previous group)

let objs = {
  1: { one: { a: 5, b: 6, c: 7, d: 8 } },
  2: { one: { a: 6, b: 9, c: 10, d: 12, e: 1 } },
  3: { one: { a: 3, b: 4, c: 9 } },
};
let groupByKey = {};
for (const obj of Object.values(objs)) {
  let [key, inerObjs] = Object.entries(obj)[0];
  groupByKey[key] ??= [];
  groupByKey[key].push(Object.entries(inerObjs));
}

let result = {};
for (const [k, arrs] of Object.entries(groupByKey)) {
  let group = {};
  for (const obj of arrs.flat()) {
    if (!group.hasOwnProperty(obj[0])) {
      group[obj[0]] = [obj[1]];
    } else {
      group[obj[0]].push(obj[1]);
    }
  }
  result[k] = group;
}
console.log(result);

CodePudding user response:

Here is a recursive option that works for objects of arbitrary depth. Here calling it in a for...of loop over the Object.values of your input in order to skip the top level properties as per your expected output.

function groupProperties(obj, res = {}) {
  for (const [k, v] of Object.entries(obj)) {
    if (typeof v === 'object') {
      groupProperties(v, (res[k] ??= {}));
    }
    else {
      (res[k] ??= []).push(v);
    }
  }

  return res;
}

const input = { 1: { one: { a: 5, b: 6, c: 7, d: 8 } }, 2: { one: { a: 6, b: 9, c: 10, d: 12, e: 1 } }, 3: { one: { a: 3, b: 4, c: 9 } }, };

const result = {};
for (const obj of Object.values(input)) {
  groupProperties(obj, result);
}

console.log(result);

  • Related