skip to Main Content

Javascript code:

const bigArray2 = [
    [1, 2, 3],
    [2, 4, 6],
    [3, 6, 9],
  ];
  
  //creates single-layer array containing all elements of every array within bigArray2
  const combinedArray = bigArray2.reduce((accumulated, current) => {
    for (element of current) {
      accumulated.push(element);
    }
    return accumulated;
  });
  

  console.log(combinedArray);
  // outputs [ 1, 2, 3, 2, 4, 6, 3, 6, 9 ] as intended
  

  console.log(bigArray2); 
  // outputs [ [ 1, 2, 3, 2, 4, 6, 3, 6, 9 ], [ 2, 4, 6 ], [ 3, 6, 9 ] ]

Somehow bigArray2[0] is assigned a value of combinedArray. How and why? .reduce() is not supposed to change the original array

2

Answers


  1. You’re not passing an initial value to your reduce() function.

    As noted on MDN:

    If initialValue is not specified, accumulator is initialized to the
    first value in the array

    When you then modify your accumulator, you’re actually modifying the first value of your input array, in this case [1, 2, 3]. Note that the original array indeed does remain unchanged. After the reduce() operation, the original array still contains the same 3 elements, i.e. the same 3 references to its sub-arrays. It’s just that by not passing an initial value, your logic ends up modifying the contents of the first of those sub-arrays.

    To fix, initialize your accumulator with an empty array ([]):

    const bigArray2 = [
      [1, 2, 3],
      [2, 4, 6],
      [3, 6, 9],
    ];
    
    const combinedArray = bigArray2.reduce((accumulated, current) => {
      for (element of current) {
        accumulated.push(element);
      }
      return accumulated;
    }, []);
    
    
    console.log(combinedArray);
    // outputs [ 1, 2, 3, 2, 4, 6, 3, 6, 9 ]
    
    
    console.log(bigArray2);
    // outputs [ [ 1, 2, 3 ], [ 2, 4, 6 ], [ 3, 6, 9 ] ]
    Login or Signup to reply.
  2. .reduce() is not supposed to change the original array

    It is perfectly possible for .reduce() to change the original array; it is more about what you do within your callback that determines whether the original array is changed or not.

    In your case, since you’re omitting the second argument to .reduce() (ie: the initial value), .reduce() will first call your callback with an accumulator set to the first item in your array. In this case, that references your first array, ie: [1, 2, 3]. As a result, since you keep on returning this same array reference value from your .reduce() callback you end up with all the values being pushed to the first array.

    To fix this, you can provide an empty array as an initial value, this way your callback will be initially called with the empty array as the accumulator, thus modifying that rather than your first element:

    const bigArray2 = [ [1, 2, 3], [2, 4, 6], [3, 6, 9], ];
    
    const combinedArray = bigArray2.reduce((accumulated, current) => {
      //   v--- declare this as const to avoid making it a global
      for (const element of current) {
        accumulated.push(element);
      }
      return accumulated;
    }, []); // <--- pass an initial array
    
    console.log(combinedArray);
    // outputs [ 1, 2, 3, 2, 4, 6, 3, 6, 9 ] as intended
    
    
    console.log(bigArray2); // left as is

    As a side note, a task like this is better done with .flat():

    const bigArray2 = [ [1, 2, 3], [2, 4, 6], [3, 6, 9], ];
    
    const combinedArray = bigArray2.flat();
    console.log(combinedArray);
    // outputs [ 1, 2, 3, 2, 4, 6, 3, 6, 9 ] as intended
    console.log(bigArray2); // left as is
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search