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?
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
forloop is the fastest. -
fillthenmapis surprisingly fast. -
Array.fromis 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
Iterator.range には期待せざる得ない
お試しあれ…
放置してるうちに本文が変わってたみたい…気にしないで下さい。
ただpushよりはうちだと3倍くらい速いです。
投稿するとミスに気づくという定番パターンで、修正したら順当に先に確保したほうが速かったです。結果を正当化する理屈で納得してしまっていました。思い込みってわい
ただなんかマークダウンのレンダリングがちょっと壊れてるような…