I have an array of objects. Basically, each object has 2 keys named id
and value
. Now I have to convert this array into an another array but with respect to ids.
Eg
const arr1 = [{
"month": "April",
"values": [{
"id": "rice",
"value": 10
},
{
"id": "wheat",
"value": 20
},
{
"id": "corn",
"value": 30
}]
},{
"month": "May",
"values": [{
"id": "rice",
"value": 40
},
{
"id": "wheat",
"value": 50
},
{
"id": "corn",
"value": 60
}]
},{
"month": "June",
"values": [{
"id": "rice",
"value": 70
},
{
"id": "wheat",
"value": 80
},
{
"id": "corn",
"value": 90
}]
}]
I want to take out values and make it something like
const arr2 = [{
id: "rice",
values: [10,40,70],
},{
id: "wheat",
values: [20,50,80],
},{
id: "corn",
values: [30,60,90],
}]
arranged in order of dates.
What I have tried
const ids = arr1[0].values.map(value => value.id);
const arr2 = ids.map(id => {
return {
id,
values:[]
}
}
I am unable to think of how to fill the values. The most obvious way will require 3 loops which should not be a good idea.
What should i do?
CodePudding user response:
const arr2 = arr1.flatMap(x => x.values);
arr2.map(x => ({
id: x.id,
value: arr2
.filter(y => y.id === x.id)
.map(y => y.value)
}));
CodePudding user response:
Here's one approach:
const extractValues = months =>
Object .entries (months
.flatMap (({values}) => values)
.reduce ((a, {id, value}) => ({...a, [id]: [...(a [id] || []), value]}), {})
) .map (([id, values]) => ({id, values}))
const months = [{month: "April", values: [{id: "rice", value: 10}, {id: "wheat", value: 20}, {id: "corn", value: 30}]}, {month: "May", values: [{id: "rice", value: 40}, {id: "wheat", value: 50}, {id: "corn", value: 60}]}, {month: "June", values: [{id: "rice", value: 70}, {id: "wheat", value: 80}, {id: "corn", value: 90}]}]
console .log (extractValues (months))
.as-console-wrapper {max-height: 100% !important; top: 0}
We start by flat-mapping the original array to combine all the value
nodes in a single array, so it will contain rice/10
, wheat/20
, corn/30
, rice/40
, ..., corn/90
, in objects like your original: {id: 'rice', value: 10}
.
Then with reduce
, we combine those into
{
rice: [10, 40, 70],
wheat: [20, 50, 80],
corn: [30, 60, 90]
}
We use Object.entries
to extract that into
[
['rice', [10, 40, 70]],
['wheat', [20, 50, 80]],
['corn', [30, 60, 90]]
]
and then we map
over them, converting this into your expected output structure.
We retain the order of the inputs, and don't try to resort by your month. That would not be much more work, but it's a reasonable guess that the data will already be sorted that way.