3

There can be multiple approach to solve this but I am not sure why this one specifically is not working as expected.

[1,2,3,4,5,6,7,8].reduce((a, d, i, c) => [...a, c.splice(0, 3)], [])

Result - [[1,2,3], [4,5,6]]

Expected Result - [[1,2,3], [4,5,6], [7,8]]

Please do not change the approach as I want to know why this one is not working as expected.

Nitish Narang
  • 4,124
  • 2
  • 15
  • 22

2 Answers2

2

I want to know why this one is not working as expected.

The problem is that you're removing entries from the original array, so reduce runs out of elements early because prior to each callback, it checks to see if the index it's about to visit is still less than the array length. After the second callback, the original array's length is 2, and the index is 2, so reduce stops, never producing the third chunk.

If you write it in its longer form, it's easier to see what's going on when you step through it in the debugger. Rather than recording a video, I'll just instrument the code:

[1,2,3,4,5,6,7,8].reduce((a, d, i, c) => {
  console.log("i", i, "c", JSON.stringify(c));
  return [...a, c.splice(0, 3)];
}, []);
.as-console-wrapper {
    max-height: 100% !important;
 }

As you can see, in the first calback all is good:

i 0 c [1,2,3,4,5,6,7,8]

it's also okay in the second callback, but notice how c is shorter now:

i 1 c [4,5,6,7,8]

After splice has done its work in that second callback, though, c will be [7, 8] and so its length is just 2. reduce stops there, because i is now 2, and it only continues when i < length is true. 2 < 2 is false, so it stops.

You can't do this reasonably with reduce. Instead, see the canonical "chunk" array question's answers. You can do it with reduceRight as Nenad Vracar points out. (Hopefully, he/she posts that as an answer.)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

This happens because you're mutating the array while iterating. In particular, the problem is that when reduce reaches the third element, there are only two elements.

[1, 2, 3, 4, 5, 6, 7, 8].reduce((a, d, i, c) => {
  console.log("current result", a)
  console.log("current element", d)
  console.log("index", i)
  console.log("array", c)
  return [...a, c.splice(0, 3)]
}, [])

So, when you get to the third iteration where i should be 2, the content of the array (c) is [7, 8]. Since that cannot work, there is no third iteration.

VLAZ
  • 26,331
  • 9
  • 49
  • 67