0

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

3
  • Would you just have the 3 keys or there can be more keys too Commented Jan 17, 2020 at 16:12
  • 2
    Arguably you'd be better off if your final output was an object instead of an array. Commented Jan 17, 2020 at 16:15
  • @ShubhamKhatri, there can be more keys! Commented Jan 17, 2020 at 17:57

4 Answers 4

2

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

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

2 Comments

if there exists more keys? This is not a general solution
There would be more keys in my case (sry i should have been more precise)
1

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
}, {})

Comments

1

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)

Comments

0

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));

1 Comment

Thanks for the explanation. Your code works in my case.

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.