1

I have this array of objects:

[
    {
        user: 'User_1',
        date: 1603926000000,
        count: 3,
    },
    {
        user: 'User_2',
        date: 1603926000000,
        count: 10,
    },
    {
        user: 'User_2',
        date: 1604876400000,
        count: 1,
    },
]

I reduce it with this function:

const reducedDataByDate = dataByDate.reduce((acc, d) => {
        const foundUser = acc.find((a) => a.user === d.user)
        const value = { date: formatDate(d.date), count: d.count }
        if (!foundUser) {
            acc.push({ user: d.user, data: [value] })
        } else {
            foundUser.data.push(value)
        }
        return acc
    }, [])

with this outcome:

[
    {
        user: 'User_1',
        data: [
            {
                date: '2020-10-29',
                count: 10,
            },
            {
                date: '2020-11-09',
                count: 1,
            },
        ],
    },
    {
        user: 'User_2',
        data: [
            {
                date: '2020-10-29',
                count: 3,
            },
        ],
    },
]

Ideally, I would like get rid of pushing values to original acc and foundUser array but have little idea how to go about that. Any input is much appreciated!

3
  • what do you want instead? Commented Nov 11, 2020 at 14:32
  • Thanks for your comment. I am looking for a way to not mutate the original array. I guess a function collectDataForUser that for a specific user collects all data then add the result of that to acc/ foundUser. Commented Nov 11, 2020 at 14:37
  • 1
    foundUser.data[foundUser.data.length] = value Commented Nov 11, 2020 at 14:37

1 Answer 1

1

You could collect the data with a Map and get the wanted format from it.

const 
    data = [{ user: 'User_1', date: 1603926000000, count: 3 }, { user: 'User_2', date: 1603926000000, count: 10 }, { user: 'User_2', date: 1604876400000, count: 1 }],
    result = Array.from(
        data.reduce(
            (m, { user, ...o }) => m.set(user, [...(m.get(user) || []), o]),
            new Map
        ),
        ([user, data]) => ({ user, data })
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, that works indeed! However, I don't really understand what's going on here ([user, data]) => ({ user, data }). Could you clear that up?
Array.from takes an iterable, the map, which is the same as Map#entries which returns an array of arrays with key/value pairs and this array is mapped by using the key/userand value/data as short hand properties for a new object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.