Как создать диапазон чисел от 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 }