Home > Net >  Merge arrays of objects with new key names in JavaScript?
Merge arrays of objects with new key names in JavaScript?

Time:01-07

Any help would be appreciated.

I have an array (A) that contains 3 arrays of objects.

A = [
[{date: '2022-12-05', value: 10.6},{date: '2022-12-06', value: 5.6},{date: '2022-12-07, value: 8.6}],
[{date: '2022-12-05', value: 4.2},{date: '2022-12-06', value: 12.3},{date: '2022-12-07, value: 9.5}],
[{date: '2022-12-05', value: 5.6},{date: '2022-12-06', value: 9.8},{date: '2022-12-07, value: 7.8}]
]

From this array (A), I need to get an array (B) that will contain the merged/concatenated arrays with new / renamed object keys (value1,value2,value3) as per the following format:

B =  [
{date: '2022-12-05', value1: 10.6, value2: 4.2, value3: 5.6},
{date: '2022-12-06', value1: 5.6, value2: 12.3, value3: 9.8},
{date: '2022-12-07', value1: 8.6, value2: 9.5, value3: 7.8}
]

The length of the first array (A) may vary (1 / 2 / 3 or more), this is why I'm struggling to find a dynamic/efficient solution.

Many thanks

CodePudding user response:

You could take a Map and collect all values.

const
    data = [[{ date: '2022-12-05', value: 10.6 }, { date: '2022-12-06', value: 5.6 }, { date: '2022-12-07', value: 8.6 }], [{ date: '2022-12-05', value: 4.2 }, { date: '2022-12-06', value: 12.3 }, { date: '2022-12-07', value: 9.5 }], [{ date: '2022-12-05', value: 5.6 }, { date: '2022-12-06', value: 9.8 }, { date: '2022-12-07', value: 7.8 }]],
    result = Array.from(
        data
            .flat()
            .reduce((m, { date, value }) => m.set(date, [...m.get(date) || [], value]), new Map),
        ([date, values]) => values.reduce((o, v, i) => ({ ...o, [`value${i   1}`]: v }), { date })
    )
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

You could use map() and reduce() functions:

const A = [
  [{date: '2022-12-05', value: 10.6},{date: '2022-12-06', value: 5.6},{date: '2022-12-07', value: 8.6}],
  [{date: '2022-12-05', value: 4.2},{date: '2022-12-06', value: 12.3},{date: '2022-12-07', value: 9.5}],
  [{date: '2022-12-05', value: 5.6},{date: '2022-12-06', value: 9.8},{date: '2022-12-07', value: 7.8}]
];

const B = A.reduce((acc, curr) => {
  curr.forEach(item => {
    const existingItem = acc.find(i => i.date === item.date);
    if (existingItem) {
      existingItem[`value${A.indexOf(curr)   1}`] = item.value;
    } else {
      acc.push({
        date: item.date,
        [`value${A.indexOf(curr)   1}`]: item.value
      });
    }
  });
  return acc;
}, []);

console.log(B);

CodePudding user response:

May i suggest a simpler data structure? Instead of numbering through the values in the form of 'value1, 'value2', ... 'valueN', you could use an array of values per date, which would make the transformation also a little bit easier as well:

const A = [
  [{date: '2022-12-05', value: 10.6},{date: '2022-12-06', value: 5.6},{date: '2022-12-07', value: 8.6}],
  [{date: '2022-12-05', value: 4.2},{date: '2022-12-06', value: 12.3},{date: '2022-12-07', value: 9.5}],
  [{date: '2022-12-05', value: 5.6},{date: '2022-12-06', value: 9.8},{date: '2022-12-07', value: 7.8}]
]

//Flatten Array
const Af = A.flat();

//Group by date
const B = Af.reduce((acc, cur) => {
  acc[cur['date']] = acc[cur['date']] ? [...acc[cur['date']], cur.value] : [cur.value]
  return acc;
}, {});

console.log(B);

  • Related