Jleu
Jleu

Reputation: 15

Array.reduce strange behaviour

Hello everyone !

I'm currently working to get a user input and parse it my way. The input represents integer ranges or single integers. Let's say I get the following ranges array :

const ranges = [`1-6`, `8`, `12-20-18`, `22-21`, `46-42-44`];

Now I need a complete integer list so I wrote this chunk :

const list = ranges.reduce ((array, range) => {
    console.log (array);
    if (!range.incldues (`-`)) return array.push (parseInt (range)); // Single integer
    const milestones = range.split (`-`).map (milestone => parseInt (milestone)),
        min = Math.min (...milestones),
        max = Math.max (...milestones);
    for (let i = min; i <= max; i++) array.push (i);
    console.log (array);
    return array;
}, []);

The thing is I quicly got a "Uncaught TypeError: array.push is not a function" and console.logging my variables showed that after the first reduce iteration, array took the value (int) 7, despite being an array just before the return statement.

Here is an illustration of it

Could someone point out where it went wrong ? How to prevent it doing so ? And furthermore, if someone could explain WHY it went wrong, it would be perfect.

Thanks !

Upvotes: 0

Views: 73

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370679

Two issues:

  • The method name is .includes (not incldues)
  • Array.prototype.push returns the new length of the array, not the array itself. Use push first, then use return array on the next line.

Fix those, and it works as expected:

const ranges = [`1-6`, `8`, `12-20-18`, `22-21`, `46-42-44`];
const list = ranges.reduce((array, range) => {
  if (!range.includes(`-`)) {
    array.push(parseInt(range)); // Single integer
    return array;
  }
  const milestones = range.split(`-`).map(Number),
    min = Math.min(...milestones),
    max = Math.max(...milestones);
  for (let i = min; i <= max; i++) array.push(i);
  return array;
}, []);
console.log(list);

Note that because the Number function converts a non-number to a number, you can simply pass it to .map rather than using .map (milestone => parseInt (milestone)) (which is a bit wordy).

Upvotes: 4

Related Questions