1

I'm looking for reduce elements of array to one object by same key (id).
I try to use Array.reduce, but cannot reduce same id elements.
Actually I don't really full understand Array.reduce's mechanism... :(
Can anybody help me?

const arr = [{id: 1, value: 1, key: 'email'}, {id: 1, value: 1, key: 'status'}, {id: 2, value: 2, key: 'email'}, {id: 2, value: 2, key: 'status'}];

// EXPECTED
const arr = [{id: 1, data: {'email': 1, 'status': 1}}, {id: 2, data: {'email': 2, 'status': 2}}];

// WHAT I DO
const result = arr.reduce((acc, cur)=>{
  const {id, key, value} = cur;
  acc.forEach(el => {
    if (el.id === id) {
      el.data[key] = value;
    }
  })
  acc = [...acc, {'id': id, 'data': { [key]: value }}];
  
  return acc
}, [])

// WHAT I GET
[
  { id: 1, data: { email: 1, status: 1 } },
  { id: 1, data: { status: 1 } },
  { id: 2, data: { email: 2, status: 2 } },
  { id: 2, data: { status: 2 } }
]
1

2 Answers 2

3

You can use Array.prototype.reduce() this way,
By group them by id as an object and then use Object.values() to get the array that you wanted:

const arr = [
  {id: 1, value: 1, key: 'email'},
  {id: 1, value: 1, key: 'status'},
  {id: 2, value: 2, key: 'email'},
  {id: 2, value: 2, key: 'status'}
];

const arr2 = [
  {id: 1, data: {'email': 1, 'status': 1}},
  {id: 2, data: {'email': 2, 'status': 2}}
];

const res = Object.values(arr.reduce((acc, curr) => {
  if(!acc[curr.id]) {
    acc[curr.id] = {
      id: curr.id,
      data: {
        [curr.key]: curr.value
      }
    }
  } else {
    acc[curr.id].data = {
      ...acc[curr.id].data,
      [curr.key]: curr.value
    }
  }

  return acc;
}, {}));

console.log(res);

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

Comments

3

Try this one

const arr = [{id: 1, value: 1, key: 'email'}, {id: 1, value: 1, key: 'status'}, {id: 2, value: 2, key: 'email'}, {id: 2, value: 2, key: 'status'}];

const result = arr.reduce((acc, {id, key, value}) => {
  const entry = acc.find(i => i.id === id);
  if (!entry) {
    acc.push({
      id, data: {
        [key]: value
      }
    });
  } else {
    entry.data[key] = value;
  }
  return acc;
}, []);

console.log(result);

1 Comment

Note: using Array.find() inside Array.reduce() is going to be expensive for larger arrays. I would recommend constructing an object with the ID as the key, and using that to build your "reduced" output. You can later manipulate that object into whatever format you would like, but the end result would be much more performant. This is all theoretical of course.

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.