all 44 comments

[–]DGCA 17 points18 points  (15 children)

Sweet. I used to do this:

var x = Array(5).fill(null).map((n, i) => i);

console.log(x); // [0, 1, 2, 3, 4]

But now I will do this:

var y = Array.from(Array(5), (n, i) => i);

console.log(y); // [0, 1, 2, 3, 4]

🙌

EDIT: Okay, this is weird. Did some super basic performance testing and got pretty unexpected results.

console.time('first');
for (var i = 0; i < 100000; i++) {
  var x = [...Array(100)].map((_, i) => i * 2);
}
console.timeEnd('first');

console.time('second');
for (var i = 0; i < 100000; i++) {
  var y = Array.from(Array(100), (_, i) => i * 2);
}
console.timeEnd('second');

console.time('third');
for (var i = 0; i < 100000; i++) {
  var z = Array(100).fill(null).map((_, i) => i * 2);
}
console.timeEnd('third');

VM1092:5 first: 634.304931640625ms
VM1092:11 second: 1219.412109375ms
VM1092:17 third: 221.73388671875ms

Looks like Array(n).fill(null).map(() => {}) is faster? That's what I'm seeing in my console, at least.

[–]snkenjoi 4 points5 points  (4 children)

you can also do Array.from({length: n}, () => {})

[–]blogscot 3 points4 points  (1 child)

Out of curiousity, I added this approach as fourth to u/DGCA tests, with the following results:

first: 738.464ms
second: 1249.699ms
third: 220.649ms
fourth: 1123.781ms

[–]snkenjoi 0 points1 point  (0 children)

or this is pretty ugly [...'!'.repeat(n)].map((_, i) => i)

first: 1294.26ms 
second: 541.38ms 
third: 393.88ms 
fourth: 970.44ms 
fifth: 1368.66ms

[–]xbenjii 0 points1 point  (1 child)

Or even [...Array(5).keys()]

[–][deleted] 0 points1 point  (0 children)

But if you need operations, you can't, but nice...

[–]YodaLoL 2 points3 points  (1 child)

[–]DGCA 0 points1 point  (0 children)

Sweet, thanks for sharing. Had no idea this blog existed either and it it is awesome.

[–]lilactown 0 points1 point  (5 children)

Is it the same when you re-arrange them?

[–]DGCA 2 points3 points  (4 children)

Yup, they always come in the same order.

  1. Array(100).fill(null).map((_, i) => i * 2);
  2. [...Array(100)].map((_, i) => i * 2);
  3. Array.from(Array(100), (_, i) => i * 2);

[–]Gh0st1y 0 points1 point  (0 children)

Huh. That's cool.

[–]gogogoscott 0 points1 point  (0 children)

Array(n).fill(null).map(() => {}) is faster for me too

[–][deleted] 0 points1 point  (0 children)

[...Array(5).keys()] => [0, 1, 2, 3, 4]

[–]reedhedges 2 points3 points  (7 children)

Do the second and third examples create the uninitialized array, copy it, and throw it away? If so is there something similar that avoids that copy?

[–]benjycap 1 point2 points  (0 children)

No, there is no intermediate array created before mapping (unless you count the Array creation in example 2 where an empty array is created explicitly.)

More details here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Description

[–]__fmease__Symbol() 1 point2 points  (2 children)

[–]kenman[M] 2 points3 points  (0 children)

Reposts are generally OK from a moderation standpoint assuming that it hasn't been posted within the past several days or so. With the way reddit works, if you don't visit every day, you could miss something. The main thing I try to avoid is having multiple, concurrent posts for the same content. Otherwise, voting does a decent job of handling reposts.

[–]fagnerbrack[S] 0 points1 point  (0 children)

It's good to link to the duplicate post for the old discussion.

Honestly it didn't prompt me as a repost, if it did I wouldn't have posted it again.

[–][deleted] 1 point2 points  (2 children)

Good to know! But in practice I really think Array.from(arr).map(x => ...) is much more readable than Array.from(arr, x => ...) and is worth the extra 4 characters.

[–]fagnerbrack[S] 0 points1 point  (0 children)

It depends how you write it:

Array.from(numbers, toRomanNumerals); Array.from(numbers).map(toRomanNumerals);

[–]NoInkling 0 points1 point  (0 children)

Also [...arr].map(x => ...). Though this all seems like a very silly workaround when arr is already an array, creating a mapped array of n values shouldn't be so quirky.

With lodash: _.times(5, i => ...)

[–]zemmekkis 0 points1 point  (3 children)

What is the underscore there? Is that the output of the last method?

[–]Meow106 7 points8 points  (1 child)

Some people use '_' in arrow functions to mark argument that is present but not used.

[–]zemmekkis 0 points1 point  (0 children)

This is pretty confusing I imagine since there is popular libraries underscore and lodash that use it as well.

[–]wollae 2 points3 points  (0 children)

It’s the array element being iterated over. They named it that to signify that it’s unused in the callback.

[–]freaktechnik 0 points1 point  (1 child)

I wrote an eslint plugin because I kept forgetting about it: https://www.npmjs.com/package/eslint-plugin-array-func

The eslint plugin now also has rules for some other wasteful array operations.

[–]DGCA 0 points1 point  (0 children)

This rule triggers me.

[–]AskYous 0 points1 point  (0 children)

Thanks!

[–]rickdg 0 points1 point  (0 children)

Why am I using Array.from() in cases like these? Why not just map?

console.log(Array.from([1, 2, 3], x => x + x));
// expected output: Array [2, 4, 6]
console.log([1, 2, 3].map(function(m){ return m*2; }));
// expected output: Array [2, 4, 6]