user11055731
user11055731

Reputation:

How do I map this result?

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

Answers (2)

Henry Ecker
Henry Ecker

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

Brandon McConnell
Brandon McConnell

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

Related Questions