Как сгенерировать диапазон чисел от 0 до n только в ES2015?

Я всегда обнаружил, что функция range отсутствует в JavaScript, поскольку она доступна в python и других? Есть ли какой-нибудь краткий способ генерации диапазона чисел в ES2015?

EDIT: мой вопрос отличается от указанного дубликата, поскольку он специфичен для ES2015, а не ECMASCRIPT-5. Также мне нужен диапазон, начинающийся с 0, а не на конкретный начальный номер (хотя было бы хорошо, если бы это было там)

Ответ 1

Вы можете использовать оператор распространения на клавишах только что созданного массива.

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

или

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

Array.from() необходим при работе с TypeScript

Ответ 2

Я также нашел еще один интуитивный способ, используя Array.from:

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

Теперь эта функция range вернет все числа, начиная с 0 до n-1

Измененная версия диапазона для поддержки start и end:

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)

Ответ 3

С дельтой

Для JavaScript

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((v, i) => 4 + i * 2);
//=> [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]

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

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

const range = (from, to, step) =>
  Array(~~((to - from) / step) + 1) // '~~' is Alternative for Math.floor()
  .fill().map((v, i) => from + i * step);

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

Array.range = (from, to, step) => Array.from({
    length: ~~((to - from) / step) + 1
  },
  (v, k) => from + k * step
);

Array.range = (from, to, step) => [...Array(~~((to - from) / step) + 1)].map(
  (v, k) => from + k * 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

// Or
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

class Range2 {
  constructor(to = 0, step = 1, from = 0) {
    this[Symbol.iterator] = function*() {
      let i = 0,
        length = ~~((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]

// Or 
const Range2 = function*(to = 0, step = 1, from = 0) {
    let i = 0, length = ~~((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, 8);
even4to10.next().value
//=> 8
even4to10.next().value
//=> 10
even4to10.next().value
//=> undefined

Для машинописи

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(~~((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(~~((to - from) / step) + 1)).map(
            (v, k) => from + k * step
        );
    }
}
_Array.range(0, 9, 1);

Ответ 4

Для чисел от 0 до 5

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

Ответ 5

Поддержка дельта

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

Ответ 6

Итак, в этом случае было бы неплохо, если бы объект Number вел себя как объект Array с оператором распространения.

Например, объект Array, используемый с оператором распространения:

let foo = [0,1,2,3];
console.log(...foo) // returns 0 1 2 3

Он работает так, потому что объект Array имеет встроенный итератор.
В нашем случае нам нужен объект Number, чтобы иметь аналогичную функциональность:

[...3] //should return [0,1,2,3]

Для этого мы можем просто создать Number iterator для этой цели.

Number.prototype[Symbol.iterator] = function *() {
   for(let i = 0; i <= this; i++)
       yield i;
}

Теперь можно создавать диапазоны от 0 до N с помощью оператора спреда.

[... N]//теперь возвращает массив 0... N

http://jsfiddle.net/01e4xdv5/4/

Приветствия.

Ответ 7

Многие из этих решений основаны на создании реальных объектов 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 }

Ответ 8

Вы также можете сделать это с помощью одного лайнера с поддержкой шагов, подобной этой:

((from, to, step) => ((add, arr, v) => add(arr, v, add))((arr, v, add) => v < to ? add(arr.concat([v]), v + step, add) : arr, [], from))(0, 10, 1)

Результат [0, 1, 2, 3, 4, 5, 6 ,7 ,8 ,9].

Ответ 9

const keys = Array(n).keys();
[...Array.from(keys)].forEach(callback);

в Typescript

Ответ 10

Здесь другой вариант, который не использует Array.

let range = (n, l=[], delta=1) => {
  if (n < 0) { 
    return l 
  }
  else {
    l.unshift(n)
    return range(n - delta, l) 
  }
}

Ответ 11

Вы можете использовать функцию генератора, которая создает диапазон лениво только тогда, когда это необходимо:

function* range(x, y) {
  while (true) {
    if (x <= y)
      yield x++;

    else
      return null;
  }
}

const infiniteRange = x =>
  range(x, Infinity);
  
console.log(
  Array.from(range(1, 10)) // [1,2,3,4,5,6,7,8,9,10]
);

console.log(
  infiniteRange(1000000).next()
);

Ответ 12

Эта функция вернет целочисленную последовательность.

const integerRange = (start, end, n = start, arr = []) =>
  (n === end) ? [...arr, n]
    : integerRange(start, end, start < end ? n + 1 : n - 1, [...arr, n]);

$> intSequence(1, 1)
<- Array [ 1 ]

$> intSequence(1, 3)
<- Array(3) [ 1, 2, 3 ]

$> intSequence(3, -3)
<- Array(7) [ 3, 2, 1, 0, -1, -2, -3 ]