Есть ли в JavaScript метод типа range () для генерации диапазона в заданных пределах? - PullRequest
653 голосов
/ 09 октября 2010

В PHP вы можете сделать ...

range(1, 3); // Array(1, 2, 3)
range("A", "C"); // Array("A", "B", "C")

То есть есть функция, которая позволяет получить диапазон чисел или символов, передав верхнюю и нижнюю границы.

Есть ли что-нибудь встроенное в JavaScript для этого? Если нет, то как бы я это реализовал?

Ответы [ 50 ]

3 голосов
/ 14 ноября 2018

Ни в одном из примеров не было тестов, реализация для шага с опцией получения убывающих значений.

export function range(start = 0, end = 0, step = 1) {
    if (start === end || step === 0) {
        return [];
    }

    const diff = Math.abs(end - start);
    const length = Math.ceil(diff / step);

    return start > end
        ? Array.from({length}, (value, key) => start - key * step)
        : Array.from({length}, (value, key) => start + key * step);

}

Тесты:

import range from './range'

describe('Range', () => {
    it('default', () => {
        expect(range()).toMatchObject([]);
    })

    it('same values', () => {
        expect(range(1,1)).toMatchObject([]);
    })

    it('step=0', () => {
        expect(range(0,1,0)).toMatchObject([]);
    })

    describe('step=1', () => {
        it('normal', () => {
            expect(range(6,12)).toMatchObject([6, 7, 8, 9, 10, 11]);
        })

        it('reversed', () => {
            expect(range(12,6)).toMatchObject([12, 11, 10, 9, 8, 7]);
        })
    })

    describe('step=5', () => {

        it('start 0 end 60', () => {
            expect(range(0, 60, 5)).toMatchObject([0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55]);
        })

        it('reversed start 60 end -1', () => {
            expect(range(55, -1, 5)).toMatchObject([55, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5, 0]);
        })
    })
})
3 голосов
/ 13 октября 2016

Вот хороший короткий способ сделать это в ES6 только с числами (не знаю, сравнивается ли его скорость):

Array.prototype.map.call(' '.repeat(1 + upper - lower), (v, i) => i + lower)

Для диапазона отдельных символов вы можете слегка его изменить:

Array.prototype.map.call(' '.repeat(1 + upper.codePointAt() - lower.codePointAt()), (v, i) => String.fromCodePoint(i + lower.codePointAt()));
2 голосов
/ 06 апреля 2019

Рекурсивное решение для генерации целочисленного массива в пределах границ.

function intSequence(start, end, n = start, arr = []) {
  return (n === end) ? arr.concat(n)
    : intSequence(start, end, start < end ? n + 1 : n - 1, arr.concat(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 ]
1 голос
/ 08 октября 2016

Нет нативного метода. Но вы можете сделать это с filter методом Array.

var range = (array, start, end) =>
      array.filter((element, index)=>index>=start && index <= end)


alert( range(['a','h','e','l','l','o','s'],1,5) )
// ['h','e','l','l','o']
1 голос
/ 07 июня 2014

Я нашел функцию диапазона JS, эквивалентную функции в PHP, и прекрасно работает здесь .Работает вперед и назад, работает с целыми числами, числами с плавающей запятой и алфавитами!

function range(low, high, step) {
  //  discuss at: http://phpjs.org/functions/range/
  // original by: Waldo Malqui Silva
  //   example 1: range ( 0, 12 );
  //   returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
  //   example 2: range( 0, 100, 10 );
  //   returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
  //   example 3: range( 'a', 'i' );
  //   returns 3: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
  //   example 4: range( 'c', 'a' );
  //   returns 4: ['c', 'b', 'a']

  var matrix = [];
  var inival, endval, plus;
  var walker = step || 1;
  var chars = false;

  if (!isNaN(low) && !isNaN(high)) {
    inival = low;
    endval = high;
  } else if (isNaN(low) && isNaN(high)) {
    chars = true;
    inival = low.charCodeAt(0);
    endval = high.charCodeAt(0);
  } else {
    inival = (isNaN(low) ? 0 : low);
    endval = (isNaN(high) ? 0 : high);
  }

  plus = ((inival > endval) ? false : true);
  if (plus) {
    while (inival <= endval) {
      matrix.push(((chars) ? String.fromCharCode(inival) : inival));
      inival += walker;
    }
  } else {
    while (inival >= endval) {
      matrix.push(((chars) ? String.fromCharCode(inival) : inival));
      inival -= walker;
    }
  }

  return matrix;
}

А вот сокращенная версия:

function range(h,c,b){var i=[];var d,f,e;var a=b||1;var g=false;if(!isNaN(h)&&!isNaN(c)){d=h;f=c}else{if(isNaN(h)&&isNaN(c)){g=true;d=h.charCodeAt(0);f=c.charCodeAt(0)}else{d=(isNaN(h)?0:h);f=(isNaN(c)?0:c)}}e=((d>f)?false:true);if(e){while(d<=f){i.push(((g)?String.fromCharCode(d):d));d+=a}}else{while(d>=f){i.push(((g)?String.fromCharCode(d):d));d-=a}}return i};
1 голос
/ 07 ноября 2015

Вот мое решение, которое имитирует Python.Внизу вы можете найти несколько примеров, как его использовать.Он работает с числами, точно так же как Python range:

var assert = require('assert');    // if you use Node, otherwise remove the asserts

var L = {};    // L, i.e. 'list'

// range(start, end, step)
L.range = function (a, b, c) {
    assert(arguments.length >= 1 && arguments.length <= 3);
    if (arguments.length === 3) {
        assert(c != 0);
    }

    var li = [],
        i,
        start, end, step,
        up = true;    // Increasing or decreasing order? Default: increasing.

    if (arguments.length === 1) {
        start = 0;
        end = a;
        step = 1;
    }

    if (arguments.length === 2) {
        start = a;
        end = b;
        step = 1;
    }

    if (arguments.length === 3) {
        start = a;
        end = b;
        step = c;
        if (c < 0) {
            up = false;
        }
    }

    if (up) {
        for (i = start; i < end; i += step) {
            li.push(i);
        }
    } else {
        for (i = start; i > end; i += step) {
            li.push(i);
        }
    }

    return li;
}

Примеры:

// range
L.range(0) -> []
L.range(1) -> [0]
L.range(2) -> [0, 1]
L.range(5) -> [0, 1, 2, 3, 4]

L.range(1, 5) -> [1, 2, 3, 4]
L.range(6, 4) -> []
L.range(-2, 2) -> [-2, -1, 0, 1]

L.range(1, 5, 1) -> [1, 2, 3, 4]
L.range(0, 10, 2) -> [0, 2, 4, 6, 8]
L.range(10, 2, -1) -> [10, 9, 8, 7, 6, 5, 4, 3]
L.range(10, 2, -2) -> [10, 8, 6, 4]
1 голос
/ 31 июля 2014

Для более рубиноподобного подхода с хорошей обратной совместимостью:

range([begin], end = 0), где begin и end - числа

var range = function(begin, end) {
  if (typeof end === "undefined") {
    end = begin; begin = 0;
  }
  var result = [], modifier = end > begin ? 1 : -1;
  for ( var i = 0; i <= Math.abs(end - begin); i++ ) {
    result.push(begin + i * modifier);
  }
  return result;
}

Примеры:

range(3); //=> [0, 1, 2, 3]
range(-2); //=> [0, -1, -2]
range(1, 2) //=> [1, 2]
range(1, -2); //=> [1, 0, -1, -2]
0 голосов
/ 24 июля 2017

Я предпочитаю путь ниже

var range = function(x, y) {
    return Array(y - x+1).fill(x).map((a, b) => {return a+b}).filter(i => i >= x);
};
console.log(range(3, 10));
0 голосов
/ 26 декабря 2018

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

Аргументы конструктора диапазона должны быть числами.Если аргумент шага пропущен, по умолчанию он равен 1. Если аргумент начала пропущен, он по умолчанию равен 0. Если шаг равен нулю, возникает ошибка.

range = (start, stop, step=1) => {
    if(step === 0) throw new Error("range() arg 3 must not be zero");

    const noStart = stop == null;
    stop = noStart ? start : stop;
    start = noStart ? 0 : start;
    const length = Math.ceil(((stop - start) / step));

    return Array.from({length}, (_, i) => (i * step) + start);
}

console.log(range(-10, 10, 2));
//output [Array] [-10,-8,-6,-4,-2,0,2,4,6,8]
console.log(range(10));
// [Array] [0,1,2,3,4,5,6,7,8,9]
console.log(3, 12);
// [Array] [3,4,5,6,7,8,9,10,11]
0 голосов
/ 21 декабря 2016

Для писем это простое ванильное решение JS, которое я придумал для генерации диапазонов букв Он предназначен для генерации массивов только заглавных или строчных букв.

function range(first, last) {
    var r = [],
        i = first.charCodeAt(0);
    
    while(i <= last.charCodeAt(0)) {
        r.push(String.fromCharCode(i++));
    }
    
    return r;
}

console.dir(range("a", "f"));
console.dir(range("G", "Z"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...