Nico Dv
Nico Dv

Reputation: 191

Merge objects of Array by key name

i would like to turn this kind of array:

let myArray = [
    { even: [2,4,6], odd: [1,3,5,7], decimals: [3.14, 12.8] },
    { even: [4,6,8], odd: [7,9,11,13], decimals: [111.1] },
    { even: [16,18], odd: [15,15,17] }
]

into:

myArray = [
    { even: [2,4,6,4,6,8,16,18] }, 
    { odd: [1,3,5,7,7,9,11,13,15,15,17] }, 
    { decimals: [3.14, 12.8, 111.1] },
]

Maybe i should use "reduce" for that, but i m not familiar with that function at all. If anyone could show me the good path

Upvotes: 0

Views: 381

Answers (4)

MadDeveloper
MadDeveloper

Reputation: 1030

Maybe I can give you a shorter and smarter answer:

myArray.reduce((acc, obj = {}) => ({
  even: [...acc.even, ...(obj.even || [])],
  odd: [...acc.odd, ...(obj.odd || [])],
  decimals: [...acc.decimals, ...(obj.decimals || [])],
}), { even: [], odd: [], decimals: []})

Reduce is very powerful, and you can use with many use case: when you want to .filter() and .map() on the same array, you can optimize it with one .reduce() call.

View .reduce() in animation: https://twitter.com/jacobmparis/status/1213887721799913479

BTW: this solution is using an object as output and not an array

Upvotes: 2

Ori Drori
Ori Drori

Reputation: 191946

Reduce the array to an accumulator object - convert each object in the original array to entries via Object.entries(), iterate the entries ([key, values]) with Array.forEach(), and concat the values with the previous values of the key.

Convert the resulting object to entries again, and map to an array of objects.

const myArray = [
  { even: [2,4,6], odd: [1,3,5,7], decimals: [3.14, 12.8] },
  { even: [4,6,8], odd: [7,9,11,13], decimals: [111.1] },
  { even: [16,18], odd: [15,15,17] }
]

const result = Object.entries( // convert the accumulator to entries
    myArray.reduce((r, o) => {
      Object.entries(o) // convert object to entries
        .forEach(([k, v]) => r[k] = [...(r[k] || []), ...v]) // add the values to the respective key in the accumulator

      return r
    }, {})
  )
  .map(([k, v]) => ({ [k]: v })) // map to objects
  
console.log(result)

Upvotes: 1

TopW3
TopW3

Reputation: 1527

I guess this format of result would be better

myArray = {
    even: [2,4,6,4,6,8,16,18], 
    odd: [1,3,5,7,7,9,11,13,15,15,17], 
    decimals: [3.14, 12.8, 111.1],
}

Below code does this.

const newObj = myArray.reduce((prev, item) => {
    for (key in item) {
        prev[key] = [...(prev[key] || []), ...item[key]]
    }

    return prev
}, {})

Upvotes: 1

Nikhil Goyal
Nikhil Goyal

Reputation: 1973

Reduce will take the first argument as a method and second as the start value. The first argument, the method, will receive two values, first will be the accumulated value till now which will be equal to the base value passed as the second argument for the first time. The second argument to the function is the current value in the array as the function will be called to iterate through each value of the array passing these two values as the parameter to the method, i.e. the first argument of reduce. Also, this first argument of the reduce function, the method, should return a value at the end which will be fed as the first argument to the method which will serve as the final accumulated value. Once the loop is over, reduce will return the final accumulated value.

Try the below code snippet. It might help you.

function mergeArray(arr) {
  // Creating the JSON from the array with all the keys and merged data.
  const json = arr.reduce((acc, curr) => {
    Object.keys(curr).forEach(k => {
      if (Object.keys(acc).includes(k)) {
        acc[k].push(...curr[k]);
      } else {
        acc[k] = curr[k];
      }
    });
    
    return acc;
  }, {});
  
  // Converting the JSON to array with each key of JSON as separate element in array.
  return Object.keys(json).map(jsonKey => {
    return {
      [jsonKey]: json[jsonKey]
    };
  });
}

let myArray = [
    { even: [2,4,6], odd: [1,3,5,7], decimals: [3.14, 12.8] },
    { even: [4,6,8], odd: [7,9,11,13], decimals: [111.1] },
    { even: [16,18], odd: [15,15,17] }
];

console.log(mergeArray(myArray));

Upvotes: 0

Related Questions