Raffel
Raffel

Reputation: 71

Grouping / Reduce array to a specific key of object

I've been struggling figuring out this problem.

So basically, i have this data (dummy)

[
    { user_id: 1, balance: 50, job: 'programmer' },
    { user_id: 1, balance: 20, job: 'teacher' },
    { user_id: 1, balance: 15, job: 'doctor' },
    { user_id: 2, balance: 5, job: 'doctor' },
    { user_id: 2, balance: 20, job: 'teacher' },
    { user_id: 3, balance: 100, job: 'teacher' },
    { user_id: 3, balance: 35, job: 'accountant' },
    { user_id: 3, balance: 40, job: 'lawyer' }
    { user_id: 3, balance: 10, job: 'programmer' }
    { user_id: 4, balance: 45, job: 'lawyer' }
]

And i want to reduce / grouping the array to be like this

[
    { user_id: 1, data: [{ balance: 50, job: 'programmer' }, { balance: 20, job: 'teacher' }, { balance: 15, job: 'doctor' }] },
    { user_id: 2, data: [{ balance: 5, job: 'doctor' }, { balance: 20, job: 'teacher' }] },
    { user_id: 3, data: [{ balance: 100, job: 'teacher' }, { 3, balance: 35, job: 'accountant' }, { balance: 40, job: 'lawyer' }, { balance: 10, job: 'programmer' }] },
    { user_id: 4, data: [{ balance: 45, job: 'lawyer' }] }
]

I've been trying to do it using .reduce

array.reduce((acc, obj) => {
    const value = obj['user_id'];
    acc[value] = (acc[value] || []).concat(obj);
    return acc;
});

But it returns not as i expected.

Please help.

Thank you so much.

Upvotes: 0

Views: 60

Answers (3)

Jonas Wilms
Jonas Wilms

Reputation: 138267

You are quite close:

 const hash = array.reduce((acc, obj) => {
   const value = obj.user_id; // typo?
   acc[value] = acc[value] || { user_id: obj.user_id, data: [] }; // initialize to an object
   acc[value].data.push(obj);
   return acc;
 }, {}); // <- use a plain object as accumulator

 const result = Object.values(hash); // turn back into array

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386604

You could take a Map and only a part of the object for the result set.

var array = [{ user_id: 1, balance: 50, job: 'programmer' }, { user_id: 1, balance: 20, job: 'teacher' }, { user_id: 1, balance: 15, job: 'doctor' }, { user_id: 2, balance: 5, job: 'doctor' }, { user_id: 2, balance: 20, job: 'teacher' }, { user_id: 3, balance: 100, job: 'teacher' }, { user_id: 3, balance: 35, job: 'accountant' }, { user_id: 3, balance: 40, job: 'lawyer' }, { user_id: 3, balance: 10, job: 'programmer' }, { user_id: 4, balance: 45, job: 'lawyer' }],
    result = Array.from(
        array.reduce((m, { user_id, ...rest }) =>
            m.set(user_id, [...(m.get(user_id) || []), rest]), new Map),
        ([user_id, data]) => ({ user_id, data })
    );

console.log(result);

Upvotes: 2

Code Maniac
Code Maniac

Reputation: 37755

You can simply use Object as your accumulator and user_id as key and than add values accordingly

let arr =[{ user_id: 1, balance: 50, job: 'programmer' },{ user_id: 1, balance: 20, job: 'teacher' },{ user_id: 1, balance: 15, job: 'doctor' },{ user_id: 2, balance: 5, job: 'doctor' },{ user_id: 2, balance: 20, job: 'teacher' },{ user_id: 3, balance: 100, job: 'teacher' },{ user_id: 3, balance: 35, job: 'accountant' },{ user_id: 3, balance: 40, job: 'lawyer' },{ user_id: 3, balance: 10, job: 'programmer' },{ user_id: 4, balance: 45, job: 'lawyer' },]

let op = arr.reduce((acc,{user_id,...rest}) => {
     acc[user_id] = acc[user_id] || {user_id,data:[]}
     acc[user_id].data.push({...rest})
    return acc;
},{});

console.log(Object.values(op))

Upvotes: 1

Related Questions