iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🗿

What is the best way to create a range array in JavaScript?

に公開
4

A debate that has existed since ancient times.

What is the best way to create a sequential array, in other words, creating [0, 1, 2, ...] from n?

It is not hard to imagine that countless helper functions have been created throughout history.

Conclusion

Create it straightforwardly with a for loop.

const arr = [];
for (let i = 0; i < len; i++) {
  arr.push(i);
}
const arr = Array(len);
for (let i = 0; i < len; i++) {
  arr[i] = i;
}

Reasons

  • Simple
  • Readable
  • Fast

One-liner approaches are all a bit quirky and not fast either.

About [...Array(length).keys()]

A common approach.

[...Array(len).keys()]

It is relatively widespread, but it is not fast. I don't think it's readable, either.

Benchmarks

  • Creating with a specified size and assigning via a for loop is the fastest.
  • fill then map is surprisingly fast.
  • Array.from is slow.
  • That said, it's only about a 20x difference, and since it's not something you repeat massively, it might all be within the margin of error.
BENCH  Summary

for { arr[i]=i } - array.bench.ts > range
    2.66x faster than for { arr.push(i) }
    4.97x faster than Array.fill.map
    10.17x faster than [...Array.keys()]
    15.49x faster than Array.from(Array)
    20.98x faster than Array.from({ length })
Details
import { describe, bench } from 'vitest';
const len = 10000;

describe('range', () => {
  bench('Array.from(Array)', () => {
    Array.from(Array(len), (_, i) => i);
  });
  bench('Array.from({ length })', () => {
    Array.from({ length: len }, (_, i) => i);
  });
  bench('[...Array.keys()]', () => {
    [...Array(len).keys()];
  });
  bench('Array.fill.map', () => {
    Array(len).fill(0).map((_, i) => i)
  })
  bench('for { arr.push(i) }', () => {
    let arr = [];
    for (let i = 0; i < len; i++) {
      arr.push(i);
    }
  });
  bench('for { arr[i]=i }', () => {
    let arr = Array(len);
    for (let i = 0; i < len; i++) {
      arr[i] = i;
    }
  });
});
 RERUN  array.bench.ts x5


 ✓ array.bench.ts > range 3693ms
     name                           hz     min     max    mean     p75     p99    p995    p999     rme  samples
   · Array.from(Array)        3,099.94  0.2300  7.4550  0.3226  0.3450  1.0200  1.6050  2.3950  ±3.80%     1550
   · Array.from({ length })   2,288.35  0.3950  0.8950  0.4370  0.4300  0.7400  0.7850  0.8900  ±0.85%     1145   slowest
   · [...Array.keys()]        4,719.29  0.1750  4.7400  0.2119  0.2000  0.4800  0.5550  1.0300  ±2.13%     2360
   · Array.fill.map           9,654.65  0.0850  0.5750  0.1036  0.1050  0.2150  0.2600  0.3700  ±0.61%     4828
   · for { arr.push(i) }     18,078.73  0.0400  3.2700  0.0553  0.0550  0.1300  0.1500  0.3550  ±1.48%     9040
   · for { arr[i]=i }        48,016.63  0.0150  0.2150  0.0208  0.0200  0.0500  0.0600  0.0900  ±0.40%    24010   fastest

 BENCH  Summary

  for { arr[i]=i } - array.bench.ts > range
    2.66x faster than for { arr.push(i) }
    4.97x faster than Array.fill.map
    10.17x faster than [...Array.keys()]
    15.49x faster than Array.from(Array)
    20.98x faster than Array.from({ length })

Others

There is actually a range proposal, which is currently at stage 2.

Discussion

dameyodamedamedameyodamedame

お試しあれ…

...
  bench('Array(len);for { arr[i]=i }', () => {
    const arr = Array(len);
    for (let i = 0; i < len; i++) {
      arr[i] = i;
    }
  });
...

放置してるうちに本文が変わってたみたい…気にしないで下さい。
ただpushよりはうちだと3倍くらい速いです。

zakurozakuro

投稿するとミスに気づくという定番パターンで、修正したら順当に先に確保したほうが速かったです。結果を正当化する理屈で納得してしまっていました。思い込みってわい