Reputation: 21
I have an array of objects.
I want to merge the objects into a single array by same key. At that time, I also want to include other value in the array together.
It doesn't matter whether the merged array is an array or an object.
Current array:
[
{
"datetime": "2022-01-10",
"a": 0.5,
"b": 80.6,
"c": 1002.2
},
{
"datetime": "2022-01-11",
"a": 0.7,
"b": 80.4,
"c": 1002.4
},
{
"datetime": "2022-01-12",
"a": 0.4,
"b": 80.2,
"c": 1002.3
}
]
Expected result:
[
[
["2022-01-10", 0.5], ["2022-01-11", 0.7], ["2022-01-12", 0.4]
],
[
["2022-01-10", 80.6], ["2022-01-11", 80.4], ["2022-01-12", 1002.4]
],
[
["2022-01-10", 1002.2], ["2022-01-11", 1002.4], ["2022-01-12", 1002.3]
]
]
or
{
"a": [
["2022-01-10", 0.5], ["2022-01-11", 0.7], ["2022-01-12", 0.4]
],
"b": [
["2022-01-10", 80.6], ["2022-01-11", 80.4], ["2022-01-12", 1002.4]
],
"c": [
["2022-01-10", 1002.2], ["2022-01-11", 1002.4], ["2022-01-12", 1002.3]
]
}
I use forEach()
and it works.
But I want to know if there are other ways.
const foo = [[], [], []];
json.forEach((item) => {
const [a, b, c] = foo;
a.push([item.datetime, item.a]);
b.push([item.datetime, item.b]);
c.push([item.datetime, item.c]);
});
Upvotes: 2
Views: 140
Reputation: 419
You can use reduce function where the initial value will be an empty object. after that, you can check if that object contains that particular key or not and push the data accordingly
a = [
{
datetime: "2022-01-10",
a: 0.5,
b: 80.6,
c: 1002.2,
},
{
datetime: "2022-01-11",
a: 0.7,
b: 80.4,
c: 1002.4,
},
{
datetime: "2022-01-12",
a: 0.4,
b: 80.2,
c: 1002.3,
},
];
const solution = (key) => {
return a.reduce((acc, { [key]: keyValue, ...next }) => {
Object.entries(next).forEach(([dataKey, dataValue]) => {
(acc[dataKey] ??= []).push([keyValue, dataValue]);
});
return acc;
}, {});
};
console.log('Solution 1: ',Object.values(solution("datetime")));
console.log('Solution 2: ',solution("datetime"));
Upvotes: 1
Reputation: 13376
As for generic solutions (only the datetime
property of each item needs to be known, thus the solutions are agnostic to all other properties) to both of the OP's use cases,
datetime
values and values of same item key
skey
s which are distinct from datetime
,one easily could use the same reduce
based approach only that
for the latter result (object based key
specific array of arrays) one passes an object as initial value and creates and aggregates the key
specific nested arrays upon the currently processed key
of each item's rest-property data-entries
,
whereas for the former result (array of arrays) the initial value is an array where one needs to create and/or access each key specific inner array by the current index of each of the rest-data's values
.
const sampleData = [{
datetime: "2022-01-10",
a: 0.5,
b: 80.6,
c: 1002.2,
}, {
datetime: "2022-01-11",
a: 0.7,
b: 80.4,
c: 1002.4,
}, {
datetime: "2022-01-12",
a: 0.4,
b: 80.2,
c: 1002.3,
}];
console.log(
sampleData
.reduce((result, { datetime, ...rest }) => {
Object
.values(rest)
.forEach((value, idx) =>
(result[idx] ??= []).push([datetime, value])
);
return result;
}, [])
);
console.log(
sampleData
.reduce((result, { datetime, ...rest }) => {
Object
.entries(rest)
.forEach(([key, value]) =>
(result[key] ??= []).push([datetime, value])
);
return result;
}, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
In case the key (insertion) order of the original array items can not be guarantied amongst all items, one should use the key
-specific second solution, where one would pass the created object to Object.values
in order to get an array of arrays ...
const sampleData = [{
datetime: "2022-01-10",
a: 0.5,
b: 80.6,
c: 1002.2,
}, {
datetime: "2022-01-11",
a: 0.7,
b: 80.4,
c: 1002.4,
}, {
datetime: "2022-01-12",
a: 0.4,
b: 80.2,
c: 1002.3,
}];
console.log(
Object
.values(
sampleData
.reduce((result, { datetime, ...rest }) => {
Object
.entries(rest)
.forEach(([key, value]) =>
(result[key] ??= []).push([datetime, value])
);
return result;
}, {})
)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Upvotes: 1
Reputation: 1
See this it uses map and then returns an array just like your ist
const data = [{
datetime: "2022-01-10",
a: 0.5,
b: 80.6,
c: 1002.2,
}, {
datetime: "2022-01-11",
a: 0.7,
b: 80.4,
c: 1002.4,
}, {
datetime: "2022-01-12",
a: 0.4,
b: 80.2,
c: 1002.3,
}];
const res = data.map((m ,_) => [
[m.datetime,m.a],
[m.datetime,m.b],
[m.datetime,m.c],
]);
console.log({ res });
Or 2nd method because of comments
const data = [{
datetime: "2022-01-10",
a: 0.5,
b: 80.6,
c: 1002.2,
}, {
datetime: "2022-01-11",
a: 0.7,
b: 80.4,
c: 1002.4,
}, {
datetime: "2022-01-12",
a: 0.4,
b: 80.2,
c: 1002.3,
}];
const res = ["a","b","c"].map(key => data.map(obj => [
obj.datetime,
obj[key],
]));
console.log({ res });
Upvotes: 0
Reputation: 1479
const Json = [
{
"datetime": "2022-01-10",
"a": 0.5,
"b": 80.6,
"c": 1002.2
},
{
"datetime": "2022-01-11",
"a": 0.7,
"b": 80.4,
"c": 1002.4
},
{
"datetime": "2022-01-12",
"a": 0.4,
"b": 80.2,
"c": 1002.3
}
]
const func = (arr, i) => {
let result = [];
const constants = ["a", "b", "c"];
for (let index = 0; index < arr.length; index++) {
result.push([arr[index].datetime, arr[index][`${constants[i]}`]]);
}
return result;
}
const result = Json.map((d, i) => {
return func(Json, i);
});
console.log(result)
Upvotes: 0
Reputation: 509
you can use javascript reduce to optimize this:
const data = temp.reduce((acc,{a,b,c,datetime})=>{
const [first,second,third] = acc;
first.push([datetime, a]);
second.push([datetime, b]);
third.push([datetime, c]);
return acc;
},[[],[],[]])
Upvotes: 0