SixtyEight
SixtyEight

Reputation: 2490

How to transform an array of arrays into an array of objects in JavasScript?

I've got some data:

const data = [
  [
    [1609459200000, 18],
    [1612137600000, 12],
    [1614556800000, 12],
    [1617231600000, 14]
  ],
  [
    [1609459200000, 30],
    [1612137600000, 501],
    [1614556800000, 81],
    [1617231600000, 82],
  ]

]

The long numbers are timestamps and I want to return an array as below:

const result = [{
  x: 1609459200000,
  y: 48
}, {
  x: 1612137600000,
  y: 513
}, {
  x: 1614556800000,
  y: 93
}, {
  x: 1617231600000,
  y: 96
}]

The X will contain the timestamp and the Y will be the sum of the values at the index 1 of each inner array, corresponding to each timestamp.

In case one of the array's element has more values than the other, it should sum it anyway as below:

const data = [
  [
    [1609459200000, 18],
    [1612137600000, 12],
    [1614556800000, 12],
    [1617231600000, 14]
  ],
  [
    [1609459200000, 30],
    [1612137600000, 501],
    [1614556800000, 81],
  ]

]

const result = [{
  x: 1609459200000,
  y: 48
}, {
  x: 1612137600000,
  y: 513
}, {
  x: 1614556800000,
  y: 93
}, {
  x: 1617231600000,
  y: 14
}]

My attempts were completely worthless and couldn't pass the part where the array is multidimensional

FAILED

const totals = data.reduce((total, curr, i) => {
  total = {
    x: curr[0][i],
    y: curr[1][i]
  }

}, {})

console.log('total', totals)

EDIT

The data array can have more than 2 sub arrays.

Upvotes: 2

Views: 64

Answers (3)

ulou
ulou

Reputation: 5853

You can achieve this in 3 steps:

  1. First you need to flat your array (even double flat in your case),
  2. Map elements into desired objects,
  3. Group by timestamp (x).

Step 2 and 3 might be swapped.

Example code:

const data = [[[16094592e5,18],[16121376e5,12],[16145568e5,12],[16172316e5,14]],[[16094592e5,30],[16121376e5,501],[16145568e5,81],[16172316e5,82]]];

const res = data.flatMap(e => e.flatMap(([x, y]) => ({x, y})))
                .reduce((acc, e) => {
                  const found = acc.find(x => x.x === e.x)
                  found ? found.y += e.y : acc.push(e)
                  return acc
                }, [])

console.log(res)
.as-console-wrapper { max-height: 100% !important; top: 0; } /* ignore this */

Upvotes: 0

Unmitigated
Unmitigated

Reputation: 89294

You can flatten the array and then perform a reduce operation over it, using an object to store the sum for each timestamp.

const data = [
  [
    [1609459200000, 18],
    [1612137600000, 12],
    [1614556800000, 12],
    [1617231600000, 14]
  ],
  [
    [1609459200000, 30],
    [1612137600000, 501],
    [1614556800000, 81],
    [1617231600000, 82],
  ]
];
const res = Object.values(data.flat().reduce((acc, [x,y])=>{
  (acc[x] ??= {x, y: 0}).y += y;
  return acc;
}, {}));
console.log(res);

Upvotes: 4

Alexander Lonberg
Alexander Lonberg

Reputation: 345

const data = [
  [
    [1609459200000, 18],
    [1612137600000, 12],
    [1614556800000, 12],
    [1617231600000, 14]
  ],
  [
    [1609459200000, 30],
    [1612137600000, 501],
    [1614556800000, 81]
  ]
]

const arr = [...data.flat()
  .reduce((a, [x, y]) => {
    a.has(x) ? (a.get(x).y += y) : a.set(x, { y })
    return a
  }, new Map())].map(([x, { y }]) => ({ x, y }))


console.log(
  arr
)

Upvotes: 0

Related Questions