Skip to content

使用给定的数字范围初始化JavaScript数组

数组初始化可以被认为是一项基本的JavaScript技能。不幸的是,JavaScript缺少一些其他语言具有的内置功能,比如Python的range()函数。让我们深入研究一下如何构建一个JavaScript的等价方法。

[!NOTE]

所有在这里介绍的方法都会生成一个包含start包含)但不包含end不包含)的数组,以保持与Python的range()方法的一致性。如果要包含end值,您需要相应地修改length公式和映射函数。

使用数字范围初始化数组

我们可以使用Array.from()来创建一个新数组。我们需要事先知道数组的length,这可以从我们想要包含的数字范围计算出来。

数组的length的一般公式是(end - start) / step。所有三个值都作为函数参数提供。为了确保length是一个整数,我们将使用Math.ceil()来向上取整结果。

const range = (end, start = 0, step = 1) =>
  Array.from(
    { length: Math.ceil((end - start) / step) },
    (_, i) => i * step + start
  );

range(5); // [0, 1, 2, 3, 4]
range(7, 3); // [3, 4, 5, 6]
range(9, 0, 2); // [0, 2, 4, 6, 8]

使用反向数字范围初始化数组

如果您想要一个反向范围,您可能会尝试在上一个代码片段的结果上使用Array.prototype.reverse()。然而,这相对低效,因为它需要两次遍历整个数组

相反,我们可以修改上面代码片段的映射函数来得到所需的结果,通过反向迭代给定的范围。为了做到这一点,我们需要将start替换为end,并取反step的值。

const rangeReverse = (end, start = 0, step = 1) =>
  Array.from(
    { length: Math.ceil((end - start) / step) },
    (_, i) => i * -step + end
  );

rangeReverse(5); // [5, 4, 3, 2, 1]
rangeReverse(7, 3); // [7, 6, 5, 4]
rangeReverse(9, 0, 2); // [9, 7, 5, 3, 1]

通用的range()函数,与Python的签名匹配

拥有两个稍微不同用途的函数并不罕见,但我们可以将解决方案推广到根据提供的参数推断正确的行为。对于反向范围,我们只需提供一个负的step值。

另一个改进是匹配Python的range()签名。这样我们可以提供(end)(start, end)(start, end, step)作为参数。注意第一个和第二个参数的顺序变化。为了实现这一点,我们将放弃参数的默认值,并使用条件语句来检查提供的参数数量

const range = (start, end, step) => {
  if (end === undefined) [end, start] = [start, 0];
  if (step === undefined) step = start < end ? 1 : -1;

  return Array.from(
    { length:  Math.ceil((end - start) / step) },
    (_, i) => i * step + start
  );
};

// 正步长值
range(5); // [0, 1, 2, 3, 4]
range(3, 7); // [3, 4, 5, 6]
range(0, 9, 2); // [0, 2, 4, 6, 8]

// 负步长值
range(5, 0, -1); // [5, 4, 3, 2, 1]
range(7, 3); // [7, 6, 5, 4]
range(9, 0, -2); // [9, 7, 5, 3, 1]