'How can I improve this JS reduce? [closed]

I have two different APIs that I've fetched from using await Promise.all(). They are assigned to a variable called items. API #1's response is an object that would look like this:

{
    total: 3,
    items: [
        {…},
        {…},
        {…}
    ]
}

API #2's response is just an array of objects.

Now I want to end up with an object looking like the response from API #1, using a reducer to add the length of API #2's to the total and ’merge’ the response from API #2 into the items array.

This is what I've gone for:

const items = results.reduce((accumulator, { response }) => {
    const total = response?.total ?? response?.length

    if(!accumulator?.items) {
        accumulator.items = []
    }

    accumulator.items = [
        ...accumulator.items,
        ...(response?.items ?? response)
    ]

    return ({
        ...accumulator,
        total: (accumulator?.total ?? 0) + total
    })
}, {})

My gut feeling is that there could definitely be a cleaner/more structured way of accomplishing the same result. Any major hiccups that I should re/-consider?



Solution 1:[1]

It seems overkill to even look at any total. You have the individual arrays, and by consequence lengths.

I would propose to use flatMap to concatenate all arrays, and only create a total property at the very end:

const results = [
    { response: { total: 3, items: [1, 2, 3] } },
    { response: [4, 5, 6, 7] }
];

const items = (items => ({ items, total: items.length }))
        (results.flatMap(({response}) => response.items ?? response));

console.log(items);

Personally, I would not create the total property at all. items.length does all you need.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1