Qubyte Codes

Tip: Array.from

#JavaScript

SPOILER ALERT: If you're doing the advent of code this year, you may not want to read onward. This post does not give any solutions away, but does contain information about how I approached a part of the first challenge.

Onward!

Today I started doing the 2017 advent of code challenges (don't worry, I won't give solutions away). The first challenge involves summing numbers in a sequence. The sequence itself is too long to express as an integer, and that wouldn't be particularly useful for the task anyway. The most convenient form is probably an array of integers. The sequence is given as raw text, and the quickest way to get it into JS is as a string.

There are a few ways to do this which spring to mind. One might argue that you can loop directly over a string anyway, but getting a list of integers avoids parsing each character in the string more than once for these tasks, so let's ignore that option.

The first thing to come to mind was a loop:

const numbers = [];

for (let i = 0; i < sequence.length; i++) {
  numbers.push(parseInt(sequence[i], 10));
}

There's a slightly nicer to read version of this introduced by ES2015:

const numbers = [];

for (const character of sequence) {
  numbers.push(parseInt(character, 10));
}

Both suffer from being a bit bulky though. ES2015 also introduced Array.from and the spread operator (...), which offer a similar way of creating an array when used in combination with Array.prototype.map:

const numbers = [...sequence].map(char => parseInt(char, 10));
// or
const numbers = Array.from(sequence).map(char => parseInt(char, 10));

The first spreads characters from the sequence into an array, and maps these characters to a fresh array of numbers. The second uses Array.from to get an array of characters from a string, and uses the same mapping to get an array of integers.

I prefer the latter of the two (it's a little easier for humans to parse). It would be nice to avoid the explicit mapping though, right? The solution I settled upon was to use the little-known second parameter to Array.from. It turns out you can include a function to map elements to be inserted into the returned array:

const numbers = Array.from(sequence, char => parseInt(char, 10));

Which is my tip! In essence, don't do this:

[...stuff].map(func);

Or this:

Array.from(stuff).map(func);

Do this:

Array.from(stuff, func);