Reputation:
This isn't an exam question or anything, I'm working on a personal project but having real brain fog on this problem. I'm hoping to get some help from the community :)
I have an array...
const result1 = [
{ "time":"17 : 30","bays":[{"number":"bay-3","availability":false},{"number":"bay-2","availability":false},{"number":"bay-1","availability":false}]},
{"time":"18 : 00","bays":[{"number":"bay-3","availability":false},{"number":"bay-2","availability":false},{"number":"bay-1","availability":false}]},
{"time":"18 : 30","bays":[{"number":"bay-3","availability":false},{"number":"bay-2","availability":false},{"number":"bay-1","availability":false}]}];
But how can I map the data from result1 to result2 in a clean esnext way?
const result2 = [
{ "number":"bay-1”,”times”:[{“time":"17 : 30","availability":false},{"time":"18 : 00","availability":false},{"time":"18 : 30","availability":false}]},
{"number":"bay-2”,”times”:[{“time":"17 : 30","availability":false},{"time":"18 : 00","availability":false},{"time":"18 : 30","availability":false}]},
{"number":"bay-3””,”times”:[{“time":"17 : 30","availability":false},{"time":"18 : 00","availability":false},{"time":"18 : 30","availability":false}]}];
Upvotes: 1
Views: 122
Reputation: 35626
You can just reduce your array to an Object keyed to the bay numbers, then convert back to a list.
const result1 = [
{
"time": "17 : 30",
"bays": [
{"number": "bay-10", "availability": false},
{"number": "bay-2", "availability": false},
{"number": "bay-1", "availability": false}
]
},
{
"time": "18 : 00",
"bays": [
{"number": "bay-10", "availability": false},
{"number": "bay-2", "availability": true},
{"number": "bay-1", "availability": false}
]
},
{
"time": "18 : 30",
"bays": [
{"number": "bay-10", "availability": true},
{"number": "bay-2", "availability": false},
{"number": "bay-1", "availability": false}
]
}];
const result2 = Object.entries(
result1.reduce((acc, {bays, time}) => {
bays.forEach(({number, availability}) => {
acc[number] = (acc[number] || []).concat({
"availability": availability,
"time": time
});
});
return acc;
}, {}
))
.reduce((acc, [bayNumber, times]) => {
return acc.concat({"number": bayNumber, "times": times});
}, [])
.sort((a, b) => a.number.localeCompare(b.number, undefined,
{numeric: true, sensitivity: 'base'}));
console.log(result2);
*I changed some values in result1
to confirm that numeric sorting of bays is correct, and that availability is appropriately mapped as the original sample had false
for all bays and times.
Upvotes: 0
Reputation: 6119
For this task, we'll first want to create a new array of the new values we'll be organizing by, in this case, the number
property. We can do this by retrieving the length of the bays
property from one of the nested objects Array(result1[0].bays.length).fill().map()
. An even simpler way to do this would be to just map()
over that same bays
property like this: result1[0].bays.map()
.
After this, we can rebuild the object in the format you need for result2
and have those new objects mapped back to the new array we are creating. To add the number
property, we can simply add it to the return object like this {number}
and for the new times
property, we'll need to iterate over the original result1
array using map()
and and retrieve the matching object under the bays
property that has a number
property value matching the one we are iterating over in our top-level array. For this, we'll only want to keep the availability
property since we are already setting the time property in the upper-level object.
result1[0].bays.map(({number}) => ({number, times: result1.map(({time, bays}) => ({time, availability: bays.find(bay => bay.number === number).availability})) }))
Finally, we'll just need to sort the returned object so that result1
is sorted by bay number, numerically. This will give you your desired result:
result1[0].bays.map(({number}) => ({number, times: result1.map(({time, bays}) => ({time, availability: bays.find(bay => bay.number === number).availability})) }))
.sort((a,b) => a.number.split('-').reverse()[0] - b.number.split('-').reverse()[0])
/* -> [
{
number: "bay-1",
times: [
{ time: "17 : 30", availability: false },
{ time: "18 : 00", availability: false },
{ time: "18 : 30", availability: false }
]
},
{
number: "bay-2",
times: [
{ time: "17 : 30", availability: false },
{ time: "18 : 00", availability: false },
{ time: "18 : 30", availability: false }
]
},
{
number: "bay-3",
times: [
{ time: "17 : 30", availability: false },
{ time: "18 : 00", availability: false },
{ time: "18 : 30", availability: false }
]
}
]
*/
We can also create a function that performs this same computation on your array(s) and returns a new array arranged by the number
property:
const result1 = [
{ time: "17 : 30", bays: [{ number: "bay-3", availability: false }, { number: "bay-2", availability: false }, { number: "bay-1", availability: false }] },
{ time: "18 : 00", bays: [{ number: "bay-3", availability: false }, { number: "bay-2", availability: false }, { number: "bay-1", availability: false }] },
{ time: "18 : 30", bays: [{ number: "bay-3", availability: false }, { number: "bay-2", availability: false }, { number: "bay-1", availability: false }] }
];
const organizeByNumber = arr => arr[0].bays.map(({number}) => ({number, times: arr.map(({time, bays}) => ({time, availability: bays.find(bay => bay.number === number).availability})) })).sort((a,b) => a.number.split('-').reverse()[0] - b.number.split('-').reverse()[0]);
const result2 = organizeByNumber(result1);
console.log(result2);
Upvotes: 1