Как создать диапазон чисел от 0 до n только в ES2015?
Я всегда находил range
функция отсутствует в JavaScript, поскольку она доступна в python и других? Есть ли какой-либо краткий способ создания диапазона чисел в ES2015 ?
EDIT: мой вопрос отличается от упомянутого дубликата, поскольку он специфичен для ES2015, а не ECMASCRIPT-5. Также мне нужно, чтобы диапазон начинался с 0, а не с определенного начального числа (хотя было бы хорошо, если бы это было там)
10 ответов:
вы можете использовать оператор spread для ключей только что созданного массива.
[...Array(n).keys()]
или
Array.from(Array(n).keys())
The
Array.from()
синтаксис необходим при работе с TypeScript
Я также нашел еще один интуитивно понятный способ с помощью
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);
EDIT Как предложил @marco6, вы можете поместить это как статический метод, если он подходит для вашего варианта использования
Array.range = (start, end) => Array.from({length: (end - start)}, (v, k) => k + start);
и использовать его как
Array.range(3, 9)
Дельта
для 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, 2, 0, -2, -4, -6, -8, -10, -12, -14] 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
Для 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(~~((to - from) / step) + 1)].map( (v, k) => from + k * step ); } } _Array.range(0, 9, 1);
для поддержки delta
const range = (start, end, delta) => { return Array.from( {length: (end - start) / delta}, (v, k) => (k * delta) + start ) };
вы также можете сделать это с одним лайнером с поддержкой шага, как этот:
((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]
.
вот еще один вариант, который не использует
Array
.let range = (n, l=[], delta=1) => { if (n < 0) { return l } else { l.unshift(n) return range(n - delta, l) } }
Итак, в этом случае, было бы неплохо, если бы объект будет вести себя как объект массива с оператором spread.
например массив объект, используемый с оператором spread:
let foo = [0,1,2,3]; console.log(...foo) // returns 0 1 2 3
это работает так, потому что объект массива имеет встроенный итератор.
В нашем случае, нам нужен объект, чтобы иметь аналогичную функциональность:[...3] //should return [0,1,2,3]
для этого мы можем просто создать итератор числа для этого цель.
Number.prototype[Symbol.iterator] = function *() { for(let i = 0; i <= this; i++) yield i; }
Теперь можно создавать диапазоны от 0 до N с помощью оператора spread.
[...N] / / теперь возвращает 0 ... Н массив
http://jsfiddle.net/01e4xdv5/4/
ваше здоровье.
многие из этих решений основаны на создании экземпляров реальных объектов массива, которые могут выполнять работу для многих случаев, но не могут поддерживать такие случаи, как
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 }