Home > Software engineering >  Transform nested object of objects of arrays in JS
Transform nested object of objects of arrays in JS

Time:09-09

Besides the horrible name of the question my question is quite simple. I have this object:

let test = {
  date1: [
    {
      time: 1,
      value: 5,
    },
    {
      time: 2,
      value: 6,
    },
  ],
  date2: [
    {
      time: 1,
      value: 20,
    },
    {
      time: 2,
      value: 10,
    },
  ],
};

That I want to transform to something like this:

let result = {
  date1: {
    values: [5, 6],
    times: [1, 2],
  },
  date2: {
    values: [1, 2], // easier to summarise?!
    times: [10, 20],
  },
};

I actually want to do this in order to summarise the value-values for each date. I thought that if I have them in an array it would be easier to summarise them. I know there are other forms to do this (and I'd be happy to see any solutions).

My current approach does not what I want it to do. It looks like this:

let keys = Object.keys(test);
let red = keys.reduce((acc, curr) => {
  return (acc[curr] = test[curr].map((e) => e.value));
}, {});

console.log(`red: `, red);

And produces this:

red: [ 20, 10 ]

CodePudding user response:

This

return (acc[curr] = test[curr].map((e) => e.value));

is equivalent to

acc[curr] = test[curr].map((e) => e.value);
return acc[curr];

going inside a nested key of the accumulator on every iteration - which isn't the logic you want. Return the whole accumulator on a separate line, so previously assigned values don't get lost, and you also need to account for both the time and value properties of the array being iterated over - your => e.value only extracts one of the two properties you want.

let test = {
  date1: [
    {
      time: 1,
      value: 5,
    },
    {
      time: 2,
      value: 6,
    },
  ],
  date2: [
    {
      time: 1,
      value: 20,
    },
    {
      time: 2,
      value: 10,
    },
  ],
};

const keys = Object.keys(test);
const result = keys.reduce((acc, key) => {
  acc[key] = {
    values: test[key].map(({ value }) => value),
    times: test[key].map(({ time }) => time),
  };
  return acc;
  return acc;
}, {});

console.log(result);

or do

let test = {
  date1: [
    {
      time: 1,
      value: 5,
    },
    {
      time: 2,
      value: 6,
    },
  ],
  date2: [
    {
      time: 1,
      value: 20,
    },
    {
      time: 2,
      value: 10,
    },
  ],
};

const result = Object.fromEntries(
  Object.entries(test).map(([key, arr]) => [
    key,
    {
      values: arr.map(({ value }) => value),
      times: arr.map(({ time }) => time),
    }
  ])
);
console.log(result);

CodePudding user response:

Try modifying it a little like this:

let result = Object.keys(test).reduce((acc, key) => {
        test[key].forEach((item) => {
            acc.push({
            date: key,
            time: item.time,
            value: item.value,
            });
        });
        return acc;
        }
    , []);
    console.log(result);

CodePudding user response:

Assuming all inner objects have the same keys and no date array is empty:

let test = {date1:[{time:1,value:5},{time:2,value:6},],date2:[{time:1,value:20},{time:2,value:10},]};

let keys = Object.keys(test);
let red = keys.reduce((acc, curr) => ({
  ...acc,
  [curr]: Object.keys(test[curr][0])
                .reduce((acc, key) => ({
                  ...acc,
                  [key   's']: test[curr].map(o => o[key])
                }), {})
}), {});

console.log(`red: `, red);

  • Related