我正在寻找以下方法的任何替代方法,以创建包含1到N的JavaScript数组,其中N仅在运行时已知。
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
对我来说,我觉得应该有一种不用循环的方法。
我正在寻找以下方法的任何替代方法,以创建包含1到N的JavaScript数组,其中N仅在运行时已知。
var foo = [];
for (var i = 1; i <= N; i++) {
foo.push(i);
}
对我来说,我觉得应该有一种不用循环的方法。
当前回答
简单量程发生器:
const min = 2000;
const max = 2022;
const range = Array.from({ length: max - min + 1 }, (v, k) => k + min);
console.log('range', range);
其他回答
对于小范围,切片是不错的。N仅在运行时已知,因此:
[0, 1, 2, 3, 4, 5].slice(0, N+1)
使用非常流行的Undercore_.range方法
// _.range([start], stop, [step])
_.range(10); // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_.range(1, 11); // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_.range(0, 30, 5); // => [0, 5, 10, 15, 20, 25]
_.range(0, -10, -1); // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
_.range(0); // => []
以下是摘要(在控制台中运行):
// setup:
var n = 10000000;
function* rangeIter(a, b) {
for (let i = a; i <= b; ++i) yield i;
}
function range(n) {
let a = []
for (; n--; a[n] = n);
return a;
}
function sequence(max, step = 1) {
return {
[Symbol.iterator]: function* () {
for (let i = 1; i <= max; i += step) yield i
}
}
}
var t0, t1, arr;
// tests
t0 = performance.now();
arr = Array.from({ length: n }, (a, i) => 1)
t1 = performance.now();
console.log("Array.from({ length: n }, (a, i) => 1) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();
arr = range(n);
t1 = performance.now();
console.log("range(n) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();
arr = Array.from(rangeIter(0, n));
t1 = performance.now();
console.log("Array.from(rangeIter(0, n)) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();
arr = [...rangeIter(0, n)];
t1 = performance.now();
console.log("[...rangeIter(0, n)] Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();
arr = Array.from(sequence(n));
t1 = performance.now();
console.log("Array.from(sequence(n)) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();
arr = [...sequence(n)];
t1 = performance.now();
console.log("[...sequence(n)] Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();
arr = Array(n).fill(0).map(Number.call, Number);
t1 = performance.now();
console.log("Array(n).fill(0).map(Number.call, Number) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();
arr = Array.from(Array(n).keys());
t1 = performance.now();
console.log("Array.from(Array(n).keys()) Took " + (t1 - t0) + " milliseconds.");
t0 = performance.now();
arr = [...Array(n).keys()];
t1 = performance.now();
console.log("[...Array(n).keys()] Took " + (t1 - t0) + " milliseconds.");
最快的是Array(n).fill(0).map(Number.call,Number),第二个是[…Array(n).keys()]
但是。。。rangeIter的方式非常方便(可以内联),速度快,功能更强大
function range(start, end) {
var foo = [];
for (var i = start; i <= end; i++) {
foo.push(i);
}
return foo;
}
然后由调用
var foo = range(1, 5);
在Javascript中没有内置的方法来实现这一点,但如果您需要多次执行,则可以创建一个非常有效的实用程序函数。
编辑:在我看来,以下是一个更好的范围函数。也许只是因为我对LINQ有偏见,但我认为它在更多情况下更有用。您的里程数可能有所不同。
function range(start, count) {
if(arguments.length == 1) {
count = start;
start = 0;
}
var foo = [];
for (var i = 0; i < count; i++) {
foo.push(start + i);
}
return foo;
}
比字符串变体简单一点:
// create range by N
Array(N).join(0).split(0);
// create a range starting with 0 as the value
Array(7).join(0).split(0).map((v, i) => i + 1) // [1, 2, 3, 4, 5, 6, 7]
更新(2018年1月4日):更新以解决确切的OP问题。感谢@lessless发出此消息!