Tip: Array.from
Published
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);