JavaScript 范围如何在 JavaScript 中创建范围
range
是一个函数,它基本上接受起始索引和结束索引,然后返回从开始到结束的所有整数的列表。
最明显的方法是使用 for 循环。
function range(start, end) {
var ans = [];
for (let i = start; i <= end; i++) {
ans.push(i);
}
return ans;
}
作为函数式编程的爱好者,我们来想一个递归解法。所以最基本的条件显然是,当起始和结束相同时,答案就是[start]
。
function range(start, end) {
if(start === end) return [start];
// recursive case
}
现在,大胆尝试一下,假设这range(start, end)
一定有效。那么问题该如何解决呢range(start, end)
?很简单!直接行动就好[start, ...range(start + 1, end)]
。
因此,将两者结合起来,我们得到
function range(start, end) {
if(start === end) return [start];
return [start, ...range(start + 1, end)];
}
在我看来,这比 for 循环的解决方案优雅得多。但我们甚至可以更进一步,使用new Array(n)
which 创建一个包含 n 个元素的数组。
如果我们有一个 n 个元素的列表,我们可以通过将每个元素映射到它的索引来从中构建一个范围,即arr.map((_, i) => i)
。
然而,根据https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Description,map
未赋值的元素不会被调用。这意味着我们需要在new Array(n)
映射之前初始化。一种标准方法是使用fill
。最终结果如下。
function range(start, end) {
return (new Array(end - start + 1)).fill(undefined).map((_, i) => i + start);
}
我们还可以利用来Array.from
创建范围:
function range(start, end) {
return Array.from({ length: end - start + 1 }, (_, i) => i)
}
感谢 Step 提到处理大范围(本质上是构建一个巨大的数组)时的效率问题。我们可以通过使用生成器来更高效地实现这一点。
function* range(start, end) {
for (let i = start; i <= end; i++) {
yield i;
}
}
我们可以在for...of
循环中使用这个生成器(这将非常高效)或者使用数组扩展来检索所有值(请注意,这本质上构建了数组,其本质上与非生成器方法相同。)
for (i of range(1, 5)) {
console.log(i);
}
/* Output
* 1 2 3 4 5 */
[...range(1, 5)] // [1, 2, 3, 4, 5]
由于我总是试图避免使用 for 循环,我们也可以按如下方式递归定义生成器。
function* range(start, end) {
yield start;
if (start === end) return;
yield* range(start + 1, end);
}
你能想到一些更酷的方法来实现这一点吗?
鏂囩珷鏉ユ簮锛�https://dev.to/ycmjason/how-to-create-range-in-javascript-539i