如何仅在 ES2015 中生成从 0 到 n 的数字范围?

IT技术 javascript arrays ecmascript-6
2021-02-12 06:17:50

我总是发现rangeJavaScript 中缺少函数,因为它在 python 和其他版本中可用?在 ES2015 中是否有任何简洁的方法来生成数字范围?

编辑:我的问题与提到的重复不同,因为它特定于 ES2015 而不是 ECMASCRIPT-5。此外,我需要范围从 0 开始,而不是特定的起始数字(尽管如果有它会很好)

6个回答

您可以在新创建的数组的键上使用扩展运算符。

[...Array(n).keys()]

或者

Array.from(Array(n).keys())

Array.from()如果与typescript工作语法是必要的

嘿@StuCox,我不知道为什么,但它将它转换为Array(5).keys().slice()切片不是数组迭代器的方法。这是它不起作用的示例typescriptlang.org/play/...
2021-03-17 06:17:50
这在typescript中不起作用,因为 keys() 返回一个数组迭代器而不是一个数组。查看 aditya-singh 的答案以获得更通用的方法。
2021-03-18 06:17:50
甜的: function range (start, end) { return [...Array(1+end-start).keys()].map(v => start+v) }
2021-03-22 06:17:50
……或Array.from(Array(n).keys())
2021-03-29 06:17:50
@DavidGonzalezShannon 你知道为什么[...Array(n).keys()]在 Typescript 中不起作用吗?是否有意偏离其他 JS 实现?
2021-04-03 06:17:50

我还发现了一种更直观的使用方法Array.from

const range = n => Array.from({length: n}, (value, key) => key)

现在这个range函数将返回从 0 到 n-1 的所有数字

的范围内的修改版本,以支持startend是:

const range = (start, end) => Array.from({length: (end - start)}, (v, k) => k + start);

编辑 正如@marco6 所建议的,如果它适合您的用例,您可以将其作为静态方法

Array.range = (start, end) => Array.from({length: (end - start)}, (v, k) => k + start);

并将其用作

Array.range(3, 9)
现在,在 javascript 中覆盖内置函数被认为是不好的做法。
2021-03-31 06:17:50
[ts] Property 'range' does not exist on type 'ArrayConstructor'. 是吗?
2021-04-08 06:17:50
好东西!为什么我们不用它扩展 Array 静态接口?在typescript中效果很好:interface ArrayConstructor { range(n: number): number[]; } Array.range = n => Array.from({length: n}, (value, key) => key); 然后无处不在Array.range(x)...
2021-04-11 06:17:50

带 Delta/Step

最小单线
[...Array(N)].map((_, i) => from + i * step);

示例和其他替代方案

[...Array(10)].map((_, i) => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]

Array.from(Array(10)).map((_, i) => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]

Array.from(Array(10).keys()).map(i => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]

[...Array(10).keys()].map(i => 4 + i * -2);
//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]

Array(10).fill(0).map((_, i) => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]

Array(10).fill().map((_, i) => 4 + i * -2);
//=> [4, 2, 0, -2, -4, -6, -8, -10, -12, -14]
范围函数
const range = (from, to, step) =>
  [...Array(Math.floor((to - from) / step) + 1)].map((_, i) => from + i * step);

range(0, 9, 2);
//=> [0, 2, 4, 6, 8]

// can also assign range function as static method in Array class (but not recommended )
Array.range = (from, to, step) =>
  [...Array(Math.floor((to - from) / step) + 1)].map((_, i) => from + i * step);

Array.range(2, 10, 2);
//=> [2, 4, 6, 8, 10]

Array.range(0, 10, 1);
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Array.range(2, 10, -1);
//=> []

Array.range(3, 0, -1);
//=> [3, 2, 1, 0]
作为迭代器
class Range {
  constructor(total = 0, step = 1, from = 0) {
    this[Symbol.iterator] = function* () {
      for (let i = 0; i < total; yield from + i++ * step) {}
    };
  }
}

[...new Range(5)]; // Five Elements
//=> [0, 1, 2, 3, 4]
[...new Range(5, 2)]; // Five Elements With Step 2
//=> [0, 2, 4, 6, 8]
[...new Range(5, -2, 10)]; // Five Elements With Step -2 From 10
//=>[10, 8, 6, 4, 2]
[...new Range(5, -2, -10)]; // Five Elements With Step -2 From -10
//=> [-10, -12, -14, -16, -18]

// Also works with for..of loop
for (i of new Range(5, -2, 10)) console.log(i);
// 10 8 6 4 2
仅作为发电机
const Range = function* (total = 0, step = 1, from = 0) {
  for (let i = 0; i < total; yield from + i++ * step) {}
};

Array.from(Range(5, -2, -10));
//=> [-10, -12, -14, -16, -18]

[...Range(5, -2, -10)]; // Five Elements With Step -2 From -10
//=> [-10, -12, -14, -16, -18]

// Also works with for..of loop
for (i of Range(5, -2, 10)) console.log(i);
// 10 8 6 4 2

// Lazy loaded way
const number0toInf = Range(Infinity);
number0toInf.next().value;
//=> 0
number0toInf.next().value;
//=> 1
// ...

从到与步骤/增量

使用迭代器
class Range2 {
  constructor(to = 0, step = 1, from = 0) {
    this[Symbol.iterator] = function* () {
      let i = 0,
        length = Math.floor((to - from) / step) + 1;
      while (i < length) yield from + i++ * step;
    };
  }
}
[...new Range2(5)]; // First 5 Whole Numbers
//=> [0, 1, 2, 3, 4, 5]

[...new Range2(5, 2)]; // From 0 to 5 with step 2
//=> [0, 2, 4]

[...new Range2(5, -2, 10)]; // From 10 to 5 with step -2
//=> [10, 8, 6]
使用发电机
const Range2 = function* (to = 0, step = 1, from = 0) {
  let i = 0,
    length = Math.floor((to - from) / step) + 1;
  while (i < length) yield from + i++ * step;
};

[...Range2(5, -2, 10)]; // From 10 to 5 with step -2
//=> [10, 8, 6]

let even4to10 = Range2(10, 2, 4);
even4to10.next().value;
//=> 4
even4to10.next().value;
//=> 6
even4to10.next().value;
//=> 8
even4to10.next().value;
//=> 10
even4to10.next().value;
//=> undefined

对于typescript

interface _Iterable extends Iterable<{}> {
  length: number;
}

class _Array<T> extends Array<T> {
  static range(from: number, to: number, step: number): number[] {
    return Array.from(
      <_Iterable>{ length: Math.floor((to - from) / step) + 1 },
      (v, k) => from + k * step
    );
  }
}
_Array.range(0, 9, 1);
//=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

更新

class _Array<T> extends Array<T> {
  static range(from: number, to: number, step: number): number[] {
    return [...Array(Math.floor((to - from) / step) + 1)].map(
      (v, k) => from + k * step
    );
  }
}
_Array.range(0, 9, 1);

编辑

class _Array<T> extends Array<T> {
  static range(from: number, to: number, step: number): number[] {
    return Array.from(Array(Math.floor((to - from) / step) + 1)).map(
      (v, k) => from + k * step
    );
  }
}
_Array.range(0, 9, 1);
您更新的 TypeScript 版本不起作用。它创建一个具有指定大小的空数组。您需要将 Array.from 与 A​​rray.keys 与 TypeScript 一起使用。Array.from(Array(~~((to - from) / step) + 1).keys())
2021-03-24 06:17:50

对于数字 0 到 5

[...Array(5).keys()];
=> [0, 1, 2, 3, 4]

许多这些解决方案建立在实例化真实的 Array 对象之上,这可以在很多情况下完成工作,但不能支持range(Infinity). 您可以使用一个简单的生成器来避免这些问题并支持无限序列:

function* range( start, end, step = 1 ){
  if( end === undefined ) [end, start] = [start, 0];
  for( let n = start; n < end; n += step ) yield n;
}

例子:

Array.from(range(10));     // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Array.from(range(10, 20)); // [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ]

i = range(10, Infinity);
i.next(); // { value: 10, done: false }
i.next(); // { value: 11, done: false }
i.next(); // { value: 12, done: false }
i.next(); // { value: 13, done: false }
i.next(); // { value: 14, done: false }