Profer
Profer

Reputation: 643

Group consecutive similar array of elements

Here is my simple array of objects

const array = [
    { name: 'a', val: '1234' },
    { name: 'b', val: '5678' },
    { name: 'c', val: '91011' },
    { name: 'c', val: '123536' },
    { name: 'e', val: '5248478' },
    { name: 'c', val: '5455' },
    { name: 'a', val: '548566' },
    { name: 'a', val: '54555' }
]

I need to group consecutive name elements and push the corresponding val. So the expected output should be

const array = [
    { name: 'a', vals: '1234' },
    { name: 'b', vals: '5678' },
    { name: 'c', vals: ['91011', '123536'] },
    { name: 'e', vals: '5248478' },
    { name: 'c', vals: '5455' },
    { name: 'a', vals: ['548566', '54555'] }
]

I tried it But could not get over it. Please help

const output = []
const result = array.reduce((a, c) => {
    if (a.name === c.name) {
        output.push(a);
    }
}, []);

Upvotes: 0

Views: 309

Answers (2)

Jonas Wilms
Jonas Wilms

Reputation: 138277

You were actually quite close:

 const output = [];
 array.reduce((a, c) => {
    if (a.name === c.name) { // current element equals previous element, lets merge
       a.values.push(c.val);
    } else output.push(a = { name: c.name, values: [c.val] ); // otherwise add new entry
    return a; // the current element is the next previous
  }  , {}); // start with an empty a, so that c always gets pushed

Note that it makes little sense to store numbers as string though.

Upvotes: 2

adiga
adiga

Reputation: 35222

You can reduce the array like this. Compare the current name with previous item's name. If they are not the same, add a new item to the accumulator. If they are the same, then use concat the merge val with the last item in accumulator. concat is used because vals could either be a string or an array.

const array = [
    { name: 'a', val: '1234' },
    { name: 'b', val: '5678' },
    { name: 'c', val: '91011' },
    { name: 'c', val: '123536' },
    { name: 'e', val: '5248478' },
    { name: 'c', val: '5455' },
    { name: 'a', val: '548566' },
    { name: 'a', val: '54555' }
]

const merged = array.reduce((acc, { name, val }, i, arr) => {
  // check if name is same as the previous name
  if (arr[i - 1] && arr[i - 1].name === name) {
    const prev = acc[acc.length - 1]; // last item in the accumulator
    prev.vals = [].concat(prev.vals, val)
  } else
    acc.push({ name, vals: val })
    
  return acc
}, [])

console.log(merged)

Upvotes: 1

Related Questions