JavaScript에는 제공된 범위 내에서 범위를 생성하는 "range ()"와 같은 메서드가 있습니까?


870

PHP에서 할 수있는 일은 ...

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

즉, 상한과 하한을 전달하여 다양한 숫자 또는 문자를 얻을 수있는 기능이 있습니다.

이를 위해 기본적으로 JavaScript가 내장되어 있습니까? 그렇지 않은 경우 어떻게 구현합니까?


1
Prototype.js에는 $R기능이 있지만 실제로는 그렇게 생각하지 않습니다.
Yi Jiang

이 (관련) 질문에 대한 훌륭한 답변이 있습니다 : stackoverflow.com/questions/6299500/…
btk

Array.from("ABC") //['A', 'B', 'C']이것이 질문의 두 번째 부분에서 찾을 수있는 가장 가까운 것입니다.
Andrew_1510

@ Andrew_1510 당신은 split("")또한 거기에서 사용할 수 있습니다
alex alex

1
연인 바운드가 0 일 때이 oneliner :Array.apply(null, { length: 10 }).map(eval.call, Number)
csharpfolk

답변:


1497

번호

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

문자 반복

String.fromCharCode(...[...Array('D'.charCodeAt(0) - 'A'.charCodeAt(0) + 1).keys()].map(i => i + 'A'.charCodeAt(0)));
 => "ABCD"

되풀이

for (const x of Array(5).keys()) {
  console.log(x, String.fromCharCode('A'.charCodeAt(0) + x));
}
 => 0,"A" 1,"B" 2,"C" 3,"D" 4,"E"

기능으로

function range(size, startAt = 0) {
    return [...Array(size).keys()].map(i => i + startAt);
}

function characterRange(startChar, endChar) {
    return String.fromCharCode(...range(endChar.charCodeAt(0) -
            startChar.charCodeAt(0), startChar.charCodeAt(0)))
}

형식화 된 함수로

function range(size:number, startAt:number = 0):ReadonlyArray<number> {
    return [...Array(size).keys()].map(i => i + startAt);
}

function characterRange(startChar:string, endChar:string):ReadonlyArray<string> {
    return String.fromCharCode(...range(endChar.charCodeAt(0) -
            startChar.charCodeAt(0), startChar.charCodeAt(0)))
}

lodash.js _.range()함수

_.range(10);
 => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_.range(1, 11);
 => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
_.range(0, 30, 5);
 => [0, 5, 10, 15, 20, 25]
_.range(0, -10, -1);
 => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
String.fromCharCode(..._.range('A'.charCodeAt(0), 'D'.charCodeAt(0) + 1));
 => "ABCD"

라이브러리가없는 오래된 비 es6 브라우저 :

Array.apply(null, Array(5)).map(function (_, i) {return i;});
 => [0, 1, 2, 3, 4]

console.log([...Array(5).keys()]);

(nils petersohn 및 기타 해설자에 대한 ES6 학점)


72
어디에서나 유용하다면 아마도 JS에서 유용 할 것입니다. (JS는 함수형 프로그래밍 유형의 작업을 수행 할 수 있으며, 범위에서 이점을 얻을 수 있습니다 (0 문. 일부 경우에 유용 할 수있는 수천 가지 이유)
Lodewijk

5
왜 단순히 사용 (new Array(5)).map(function (value, index) { return index; })이 효과가 없는지 아십니까? 이것은 [undefined × 5]Chrome DevTools에서 나에게 돌아옵니다 .
Lewis

12
@Lewis 이것으로 정의 된 배열에는 슬롯이 map()있거나 그중 하나의 친구 와 반복되지 않습니다 .
alex

65
Array.from (Array (5) .keys ())
nils petersohn

17
Array(5).fill()또한 매핑 가능
nils petersohn

332

숫자의 경우 ES6을 사용할 수 있습니다 Array.from() , 요즘 모든 작동 IE를 제외한를 :

더 짧은 버전 :

Array.from({length: 20}, (x,i) => i);

더 긴 버전 :

Array.from(new Array(20), (x,i) => i)

0에서 19까지의 배열을 만듭니다. 이것은 다음 형식 중 하나로 더 단축 될 수 있습니다.

Array.from(Array(20).keys())
// or
[...Array(20).keys()]

예를 들어 하한과 상한도 지정할 수 있습니다.

Array.from(new Array(20), (x,i) => i + *lowerBound*)

이를 자세히 설명하는 기사 : http://www.2ality.com/2014/05/es6-array-methods.html


50
첫 번째 예는 [... Array (20) .keys ()]로 단순화 될 수도 있습니다.
Delapouite

27
Array.from()방법 보다 약간 간결 하고 둘 다 더 빠릅니다.Array(20).fill().map((_, i) => i)
Stu Cox

2
트윗 담아 가기 별도의 답변을해야합니다. 투표하겠습니다. 또한 이 복제본에 대한 완벽한 해답 입니다.
jib

9
@Delapouite @jib 그리고 이것 또한 :Array.from({length: end - start}, (v, k) => k + start)
Aditya Singh

1
자바 스크립트를 전달과 동일하게 정의 된 함수 인수를 생략하더라도 @ icc97 예, 린터가 불평 할 수 undefined있으므로, fill()(인수없이하는 것은) 아니다 잘못 그 자체. 채우기 값은 해당 솔루션에서 사용되지 않으므로 원하는 경우 fill(0)몇 문자를 저장하는 데 사용할 수 있습니다 .
Stu Cox

122

내가 가장 좋아하는 양식 ( ES2015 )

Array(10).fill(1).map((x, y) => x + y)

그리고 step매개 변수 가있는 함수가 필요한 경우 :

const range = (start, stop, step = 1) =>
  Array(Math.ceil((stop - start) / step)).fill(start).map((x, y) => x + y * step)

5
let range = (start, stop, step = 1) => Array (stop-start) .fill (start) .map ((x, y) => x + y * step)
rodfersou

4
@rodfersou 참고 : 귀하의 예가 잘못되었습니다. stop실제로 정지 / 종료 위치가 아니라 카운트 / 거리입니다. (
오해

4
혼란스러워-F Lekschas의 의견에 따른 rodfersou의 편집으로 인해 그의 코드는 이제 정확합니다.
eedrah

1
당신이 전달하는 인수는 PHP의 "포괄적 인"행동을 실제로 모방하기 위해 끝에 Array(Math.ceil((stop - start) / step) + 1)필요합니다 +1.
Johan Dettmar

3
이것은 실제로 range메소드 를 완전히 구현하는 Javascript 함수의 전체 질문에 대답하는 최상위 답변입니다 . 현재이 위에있는 다른 모든 것 (lodash 's 제외 _.range)은 시작, 중지 및 단계를 사용하여 실제 범위 함수 대신 기본 반복자를 구현합니다.
icc97

99

여기 내 2 센트가 있습니다 :

function range(start, count) {
  return Array.apply(0, Array(count))
    .map((element, index) => index + start);
}

1
고차 함수의 탁월한 사용.
Farzad YZ

5
질문이 시작 및 종료 값을 요청하기 때문에 실제로 잘못되었습니다. 시작 및 카운트 / 거리가 아닙니다.
James Robey

73

선택적 단계로 앞뒤로 문자와 숫자에 적용됩니다.

var range = function(start, end, step) {
    var range = [];
    var typeofStart = typeof start;
    var typeofEnd = typeof end;

    if (step === 0) {
        throw TypeError("Step cannot be zero.");
    }

    if (typeofStart == "undefined" || typeofEnd == "undefined") {
        throw TypeError("Must pass start and end arguments.");
    } else if (typeofStart != typeofEnd) {
        throw TypeError("Start and end arguments must be of same type.");
    }

    typeof step == "undefined" && (step = 1);

    if (end < start) {
        step = -step;
    }

    if (typeofStart == "number") {

        while (step > 0 ? end >= start : end <= start) {
            range.push(start);
            start += step;
        }

    } else if (typeofStart == "string") {

        if (start.length != 1 || end.length != 1) {
            throw TypeError("Only strings with one character are supported.");
        }

        start = start.charCodeAt(0);
        end = end.charCodeAt(0);

        while (step > 0 ? end >= start : end <= start) {
            range.push(String.fromCharCode(start));
            start += step;
        }

    } else {
        throw TypeError("Only string and number types are supported");
    }

    return range;

}

jsFiddle .

기본 유형을 보강하는 것이 필요한 경우에 지정하십시오 Array.range.


53

간단한 범위 기능 :

function range(start, stop, step) {
    var a = [start], b = start;
    while (b < stop) {
        a.push(b += step || 1);
    }
    return a;
}

BitInt 데이터 형식 을 통합 하기 위해 모든 변수가 동일한 지 확인하는 몇 가지 검사가 포함될 수 있습니다 typeof start.

function range(start, stop, step) {
    var a = [start], b = start;
    if (typeof start == 'bigint') {
        stop = BigInt(stop)
        step = step? BigInt(step): 1n;
    } else
        step = step || 1;
    while (b < stop) {
        a.push(b += step);
    }
    return a;
}

stop예를 들어에 의해 정의 된 것보다 높은 값을 제거하려면 range(0,5,2)포함 6해서는 안됩니다.

function range(start, stop, step) {
    var a = [start], b = start;
    while (b < stop) {
        a.push(b += step || 1);
    }
    return (b > stop) ? a.slice(0,-1) : a;
}

3
사용 가능하고 읽기 쉬운 PLUS UNO 오랫동안 본 최고의 코드 스 니펫.
monsto

1
이 경우 작동하지 않습니다 step != 11, while조건이 취할 필요가 step고려. 기본값으로 업데이트 된 버전 step: function range (start, stop, step) {step = step || 1 var a = [시작], b = 시작; while ((b + step) <stop) {console.log ( "b :"+ b + ". a :"+ a + "."); b + = 단계; a. 푸시 (b); } 반환 a; }
daveharris

@daveharris 위의 기본 단계를 추가했습니다 (step || 1).
Mr. Polywhirl

36
Array.range= function(a, b, step){
    var A= [];
    if(typeof a== 'number'){
        A[0]= a;
        step= step || 1;
        while(a+step<= b){
            A[A.length]= a+= step;
        }
    }
    else{
        var s= 'abcdefghijklmnopqrstuvwxyz';
        if(a=== a.toUpperCase()){
            b=b.toUpperCase();
            s= s.toUpperCase();
        }
        s= s.substring(s.indexOf(a), s.indexOf(b)+ 1);
        A= s.split('');        
    }
    return A;
}


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

    Array.range(-100,100,20);
    // [-100,-80,-60,-40,-20,0,20,40,60,80,100]

    Array.range('A','F');
    // ['A','B','C','D','E','F')

    Array.range('m','r');
    // ['m','n','o','p','q','r']

Array프로토 타입에 메서드를 만들지 말아야합니다 .
connectyourcharger

이 방법은 정수와 문자로만 작동합니다. 매개 변수가 null, undefined, NaN, boolean, array, object 등이면이 메서드는 다음 오류를 반환합니다. undefined method toUpperCase to etc!
Victor

```if (typeof from! == 'number'&& typeof from! == 'string') {throw new TypeError ( '첫 번째 매개 변수는 숫자 또는 문자 여야합니다')} if if (typeof to! == ' number '&& typeof to! =='string ') {throw new TypeError ('첫 번째 매개 변수는 숫자 또는 문자 여야합니다 ')}```
Victor

36

자, JavaScript에는 PHPrange() 와 같은 함수 가 없으므로 매우 쉬운 함수를 만들어야합니다. 한 줄 함수 몇 개를 작성 하고 아래와 같이 숫자알파벳 으로 구분합니다.

에 대한 번호 :

function numberRange (start, end) {
  return new Array(end - start).fill().map((d, i) => i + start);
}

다음과 같이 호출하십시오.

numberRange(5, 10); //[5, 6, 7, 8, 9]

대한 알파벳 :

function alphabetRange (start, end) {
  return new Array(end.charCodeAt(0) - start.charCodeAt(0)).fill().map((d, i) => String.fromCharCode(i + start.charCodeAt(0)));
}

다음과 같이 호출하십시오.

alphabetRange('c', 'h'); //["c", "d", "e", "f", "g"]

2
이 기능에는 일대일 오류가 있다고 생각합니다. 해야 Array(end - start + 1)하고 Array(end.charCodeAt(0) - start.charCodeAt(0) + 1).
earcanal

24

트릭을 수행하는 편리한 기능, 아래 코드 스 니펫을 실행하십시오.

function range(start, end, step, offset) {
  
  var len = (Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1;
  var direction = start < end ? 1 : -1;
  var startingPoint = start - (direction * (offset || 0));
  var stepSize = direction * (step || 1);
  
  return Array(len).fill(0).map(function(_, index) {
    return startingPoint + (stepSize * index);
  });
  
}

console.log('range(1, 5)=> ' + range(1, 5));
console.log('range(5, 1)=> ' + range(5, 1));
console.log('range(5, 5)=> ' + range(5, 5));
console.log('range(-5, 5)=> ' + range(-5, 5));
console.log('range(-10, 5, 5)=> ' + range(-10, 5, 5));
console.log('range(1, 5, 1, 2)=> ' + range(1, 5, 1, 2));

사용 방법은 다음과 같습니다

범위 (시작, 종료, 단계 = 1, 오프셋 = 0);

  • 포함-앞으로 range(5,10) // [5, 6, 7, 8, 9, 10]
  • 포함-뒤로 range(10,5) // [10, 9, 8, 7, 6, 5]
  • 단계-뒤로 range(10,2,2) // [10, 8, 6, 4, 2]
  • 독점-앞으로 range(5,10,0,-1) // [6, 7, 8, 9] not 5,10 themselves
  • 오프셋-확장 range(5,10,0,1) // [4, 5, 6, 7, 8, 9, 10, 11]
  • 오프셋-축소 range(5,10,0,-2) // [7, 8]
  • 단계-확장 range(10,0,2,2) // [12, 10, 8, 6, 4, 2, 0, -2]

도움이 되길 바랍니다.


그리고 그것이 어떻게 작동하는지 여기에 있습니다.

기본적으로 먼저 결과 배열의 길이를 계산하고 해당 길이의 0으로 채워진 배열을 만든 다음 필요한 값으로 채 웁니다.

  • (step || 1)=> 그리고 이와 같은 다른 사람들은 값을 사용하고 step그것이 제공되지 않았다면1 대신 합니다.
  • 다음을 사용하여 결과 배열의 길이를 계산하여 시작합니다. (Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1) 더 간단하게 (양방향 / 단계의 차이 * 오프셋)
  • 길이를 얻은 후 check here을 사용하여 초기화 된 값으로 빈 배열을 만듭니다.new Array(length).fill(0);
  • 이제 [0,0,0,..]원하는 길이 의 배열 이 있습니다. 우리는 그것을 매핑하고 필요한 값을 가진 새로운 배열을 반환합니다.Array.map(function() {})
  • var direction = start < end ? 1 : 0;분명히 start보다 작지 않은 경우end 우리는 뒤로 이동해야합니다. 나는 0에서 5로 또는 그 반대로가는 것을 의미합니다.
  • 반복 할 때마다 startingPoint+ stepSize* index는 우리에게 필요한 가치를 제공합니다

8
핸디, 가장 확실합니다. 단순한? 나는달라고 간청한다. 당신이 그것을 하나의 라이너로 만들지 않더라도. 파이썬에서 오는 것은 충격입니다.
PascalVKooten

@PascalvKooten, 물론 파이썬과 같은 내장 메소드가 있다면 좋았을 것입니다. 그러나 이것이 내가 얻을 수있는 가장 간단한 방법이었습니다. 그리고 그것은 내 프로젝트에서 편리하다는 것이 입증되었습니다.
azerafati

고통스럽고 복잡한 코드 스 니펫을 게시하십시오. 특히 단일 라이너로 작동하는 방법에 대한 설명이 없습니까? "작동"여부에 관계없이 좋은 SO 답변의 예가 잘못되었습니다.
Madbreaks

1
@Madbreaks, 맞아. 나는 그것을 하나의 라이너로 만들기 위해 순진했습니다. 모두에게 빠르고 쉬운 솔루션을 제공하고 싶었습니다
azerafati

22
var range = (l,r) => new Array(r - l).fill().map((_,k) => k + l);

@nikkwong _은 매핑 콜백에서 인수의 이름 일뿐입니다. 일부 언어 _에서는 변수를 사용하지 않음을 나타 내기 위해 이름으로를 사용합니다.
Klesun

그러나에 _대한 인수를 통해 전달되지는 않습니다 range. 왜 안돼?
nikk wong

2
매우 깔끔합니다! 그러나 IE 또는 Opera에서는 작동하지 않습니다.
Rafael Xavier

4
이 답변은 SO에 적합하지 않기 때문에 설명이 필요합니다.
Madbreaks

@RafaelXavier 함께 IE에서 작동 ) (Array.fill polyfill
mwag

18

하모니 스프레드 연산자 및 화살표 기능 사용 :

var range = (start, end) => [...Array(end - start + 1)].map((_, i) => start + i);

예:

range(10, 15);
[ 10, 11, 12, 13, 14, 15 ]

그게 가장 좋은 대답입니다!
Henry H.

1
그러나 가장 빠르지는 않습니다.
mjwrazor 2016 년

이 경우 밑줄 '_'기호는 무엇을 나타 냅니까?
Oleh Berehovskyi 2019

@OlehBerehovskyi 실제로 사용하려는 의도가없는 람다 함수 매개 변수를 의미합니다. 사용되지 않는 변수에 대해 경고하는 린 터는이를 무시해야합니다.
Micah Zoltu

18

--- 업데이트 (간단히 @lokhmakov에게 감사드립니다) ---

ES6 생성기를 사용하는 다른 버전 (ES6 생성기로 Paolo Moretti의 훌륭한 답변 참조 )

const RANGE = (x,y) => Array.from((function*(){
  while (x <= y) yield x++;
})());

console.log(RANGE(3,7));  // [ 3, 4, 5, 6, 7 ]

또는 반복 가능 해야하는 경우 :

const RANGE_ITER = (x,y) => (function*(){
  while (x <= y) yield x++;
})();

for (let n of RANGE_ITER(3,7)){
  console.log(n);
}

// 3
// 4
// 5
// 6
// 7

--- 원래 코드는 다음과 같습니다. ---

const RANGE = (a,b) => Array.from((function*(x,y){
  while (x <= y) yield x++;
})(a,b));

const RANGE_ITER = (a,b) => (function*(x,y){
  while (x <= y) yield x++;
})(a,b);

1
그냥 const range = (x, y) => Array.from(function* () { while (x <= y) yield x++; }())
lokhmakov

@lokhmakov 네, 맞습니다. 감사합니다! 내 대답에 코드를 적용했습니다.
영웅 Qu

15

다양한 Range 함수에 대한 연구를 수행했습니다. 이러한 기능을 수행하는 다른 방법 의 jsperf 비교 를 확인하십시오. 확실히 완벽하거나 철저한 목록은 아니지만 도움이되어야합니다 :)

우승자는 ...

function range(lowEnd,highEnd){
    var arr = [],
    c = highEnd - lowEnd + 1;
    while ( c-- ) {
        arr[c] = highEnd--
    }
    return arr;
}
range(0,31);

기술적으로 파이어 폭스에서 가장 빠르지는 않지만 크롬의 미친 속도 차이 (imho)가 그것을 보완합니다.

또한 흥미로운 사실은 파이어 폭스보다 이러한 배열 기능으로 크롬이 얼마나 빠르다는 것입니다. 크롬은 적어도 4 ~ 5 배 빠릅니다 .


참고 이것은 스텝 크기 파라미터에 포함 범위의 함수와 비교했다
binaryfunt

15

표준 Javascript에는 범위를 생성하는 내장 함수가 없습니다. 몇몇 자바 스크립트 프레임 워크는 이러한 기능에 대한 지원을 추가하거나 다른 사람들이 지적했듯이 항상 자신의 롤을 할 수 있다고 지적했습니다.

다시 확인하려면 결정적인 리소스는 ECMA-262 Standard 입니다.


2010 년에는 완벽한 대답이 확실하지만 더 이상 최선의 방법으로 생각해서는 안됩니다. Prototype.js가 👍을하는 경향이있는 것처럼 빌트인 타입을 확장해서는 안됩니다
Dana Woodman

@DanaWoodman이 문제를 제기 해 주셔서 감사합니다-Prototype.js에 대한 참조를 2018 년에 실제로 폐기 된 이후로 답변을 업데이트했습니다.
Mike Dinescu

20
글쎄, 이것은 전혀 도움이되지 않았습니다.
Pithikos

@ Pithikos 나는이 질문이 원래 요청 된 이후 편집 된 것으로 보았고 OP는 JS에 기본 범위 함수가 있는지 알고 싶어했습니다.
마이크 디네 스쿠

13

당신이 사용할 수있는 lodash 또는 Undescore.js를 range .

var range = require('lodash/range')
range(10)
// -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

또는 연속적인 정수 범위 만 필요한 경우 다음과 같은 작업을 수행 할 수 있습니다.

Array.apply(undefined, { length: 10 }).map(Number.call, Number)
// -> [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

ES6에서는 생성기range 로 구현할 수 있습니다 .

function* range(start=0, end=null, step=1) {
  if (end == null) {
    end = start;
    start = 0;
  }

  for (let i=start; i < end; i+=step) {
    yield i;
  }
}

이 구현은 모든 값을 배열로 구체화 할 필요가 없으므로 큰 시퀀스를 반복 할 때 메모리를 절약합니다.

for (let i of range(1, oneZillion)) {
  console.log(i);
}

ES6 부분은 이제이 질문에 대한 정답입니다. 다른 답변으로 덮여있는 다른 부분을 제거하는 것이 좋습니다.
joews

x = range (1, 10); // {} x; // {} //는 빈 맵 WTF처럼 보입니다!?! x.next (). value; // OK 1; x [3] // 실제 배열에서만 정의되지 않음
Anona112

@ Anona112를 사용 Array.from하면 생성기를 어레이 인스턴스로 변환하고 출력을 검사하는 데 사용할 수 있습니다 .
Paolo Moretti

10

재미있는 과제는이를 위해 가장 짧은 함수를 작성하는 것 입니다. 구조 재귀!

function r(a,b){return a>b?[]:[a].concat(r(++a,b))}

넓은 범위에서는 속도가 느리지 만 운 좋게도 양자 컴퓨터는 모퉁이에 있습니다.

추가 보너스는 난독 화한다는 것입니다. 우리 모두가 코드를 훔쳐 보지 않도록 숨기는 것이 얼마나 중요한지 알고 있기 때문입니다.

기능을 진정으로 완전히 난독 화하려면 다음을 수행하십시오.

function r(a,b){return (a<b?[a,b].concat(r(++a,--b)):a>b?[]:[a]).sort(function(a,b){return a-b})}

4
짧게! = 간단하지만 더 간단합니다. const range = (a, b) => (a>=b) ? [] : [a, ...range(a+1, b)]ES6 구문을 사용하여 버전을보다 쉽게 ​​읽을 수 있습니다.
nafg

1
@nafg : const range = (a, b, Δ = 1) => (a > b) ? [] : [a, ...range(a + Δ, b, Δ)];. 또한 의견에 대한 전체 답변을지지합니다.
7vujy0f0hy

10

이것이 최선의 방법이 아닐 수도 있습니다. 그러나 한 줄의 코드로 다양한 숫자를 얻으려는 경우. 예를 들어 10-50

Array(40).fill(undefined).map((n, i) => i + 10)

여기서 40은 (끝-시작)이고 10은 시작입니다. 이것은 [10, 11, ..., 50]을 반환해야합니다


9

나는 이런 식으로 코딩 할 것이다 :

function range(start, end) {
    return Array(end-start).join(0).split(0).map(function(val, id) {return id+start});
}  

range(-4,2);
// [-4,-3,-2,-1,0,1]

range(3,9);
// [3,4,5,6,7,8]

파이썬 범위와 비슷하게 동작합니다 :

>>> range(-4,2)
[-4, -3, -2, -1, 0, 1]

8

ES6을 많이 사용하는 다소 최소한의 구현은 다음과 같이 만들 수 있으며 Array.from()정적 방법에 특히주의를 기울입니다 .

const getRange = (start, stop) => Array.from(
  new Array((stop - start) + 1),
  (_, i) => i + start
);

부수적으로, 나는 "향상된" getRange()기능을 만드는 Gist를 만들었습니다 . 특히, 위의 베어 본 변형에서 다루어지지 않은 엣지 케이스를 캡처하는 것을 목표로했습니다. 또한 영숫자 범위에 대한 지원을 추가했습니다. 다시 말해, 'C'and 'K'(순서대로) 와 같이 두 개의 입력을 사용하여 호출하면 값은 문자 'C'(포함)부터 문자 'K'(제외)까지 순차적 문자 세트 인 배열을 리턴합니다.getRange('C', 'K'); // => ["C", "D", "E", "F", "G", "H", "I", "J"]
IsenrichO

당신은 new키워드 가 필요하지 않습니다
Soldeplata Saketos

8

range(start,end,step): ES6 반복자와 함께

상한과 하한 만 요구합니다. 여기서 우리는 한 걸음 한 걸음도 만듭니다.

range()반복자로 기능 할 수있는 생성기 기능을 쉽게 만들 수 있습니다 . 즉, 전체 어레이를 미리 생성 할 필요가 없습니다.

function * range ( start, end, step = 1 ) {
  let state = start;
  while ( state < end ) {
    yield state;
    state += step;
  }
  return;
};

이제 반복자에서 배열을 미리 생성하고 목록을 반환하는 것을 만들 수 있습니다. 이것은 배열을 받아들이는 함수에 유용합니다. 이를 위해 우리는 사용할 수 있습니다Array.from()

const generate_array = (start,end,step) =>
  Array.from( range(start,end,step) );

이제 정적 배열을 쉽게 생성 할 수 있습니다.

const array1 = generate_array(1,10,2);
const array1 = generate_array(1,7);

그러나 무언가가 반복자를 원하거나 반복자를 사용할 수있는 옵션을 제공하면 쉽게 반복자를 만들 수 있습니다.

for ( const i of range(1, Number.MAX_SAFE_INTEGER, 7) ) {
  console.log(i)
}

특별 노트


7

이은 아니지만 PHP 만의 모방 range에서 파이썬 .

function range(start, end) {
    var total = [];

    if (!end) {
        end = start;
        start = 0;
    }

    for (var i = start; i < end; i += 1) {
        total.push(i);
    }

    return total;
}

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

가장 빠른 +1 -36768-36768의 배열로 3ms가 걸리고 2 위는 13ms이며 IDE 빨간색 선이 있습니다.
mjwrazor 2016 년

7

주어진 범위에 대한 숫자 배열을 생성하는 한, 나는 이것을 사용합니다 :

function range(start, stop)
{
    var array = [];

    var length = stop - start; 

    for (var i = 0; i <= length; i++) { 
        array[i] = start;
        start++;
    }

    return array;
}

console.log(range(1, 7));  // [1,2,3,4,5,6,7]
console.log(range(5, 10)); // [5,6,7,8,9,10]
console.log(range(-2, 3)); // [-2,-1,0,1,2,3]

알파벳 배열에서는 작동하지 않습니다.


array = []루프 내부를 설정 하면 원하는 것을 얻지 못할 수 있습니다.
alex

@alex, 감사합니다. 당신도 그렇습니다, 나는 또한 루프의 각 패스에서 "start"파라미터를 증가시키는 것을 잊었습니다. 이제 수정되었습니다.
jhaskell

원하는 출력을 생성하지 못합니다. 범위 5-10을 원하면 나에게 줄 것 [5, 6, 7, 8, 9, 10, 11, 12, 13, 14]입니다. 그 배열의 처음 절반 만 기대합니다.
alex

@ alex, 다시 한 번 감사드립니다. 입력을 기반으로 길이 제한을 고려하지 않았습니다. 업데이트 된 버전을 참조하십시오.
jhaskell

6

IE11을 제외한 모든 브라우저 에서 지원되는 하모니 생성기 사용 :

var take = function (amount, generator) {
    var a = [];

    try {
        while (amount) {
            a.push(generator.next());
            amount -= 1;
        }
    } catch (e) {}

    return a;
};

var takeAll = function (gen) {
    var a = [],
        x;

    try {
        do {
            x = a.push(gen.next());
        } while (x);
    } catch (e) {}

    return a;
};

var range = (function (d) {
    var unlimited = (typeof d.to === "undefined");

    if (typeof d.from === "undefined") {
        d.from = 0;
    }

    if (typeof d.step === "undefined") {
        if (unlimited) {
            d.step = 1;
        }
    } else {
        if (typeof d.from !== "string") {
            if (d.from < d.to) {
                d.step = 1;
            } else {
                d.step = -1;
            }
        } else {
            if (d.from.charCodeAt(0) < d.to.charCodeAt(0)) {
                d.step = 1;
            } else {
                d.step = -1;
            }
        }
    }

    if (typeof d.from === "string") {
        for (let i = d.from.charCodeAt(0); (d.step > 0) ? (unlimited ? true : i <= d.to.charCodeAt(0)) : (i >= d.to.charCodeAt(0)); i += d.step) {
            yield String.fromCharCode(i);
        }
    } else {
        for (let i = d.from; (d.step > 0) ? (unlimited ? true : i <= d.to) : (i >= d.to); i += d.step) {
            yield i;
        }
    }
});

갖다

예 1.

take 얻을 수있는만큼만 걸립니다

take(10, range( {from: 100, step: 5, to: 120} ) )

보고

[100, 105, 110, 115, 120]

예 2.

to 필요하지 않은

take(10, range( {from: 100, step: 5} ) )

보고

[100, 105, 110, 115, 120, 125, 130, 135, 140, 145]

모두 가져가

실시 예 3.

from 필요하지 않은

takeAll( range( {to: 5} ) )

보고

[0, 1, 2, 3, 4, 5]

실시 예 4.

takeAll( range( {to: 500, step: 100} ) )

보고

[0, 100, 200, 300, 400, 500]

실시 예 5.

takeAll( range( {from: 'z', to: 'a'} ) )

보고

["z", "y", "x", "w", "v", "u", "t", "s", "r", "q", "p", "o", "n", "m", "l", "k", "j", "i", "h", "g", "f", "e", "d", "c", "b", "a"]


내 제안으로 편집 :)
Xotic750

접근 방식으로 +1 @alex의 관점에서, for절 에 삼항 연산 (특히 중첩되지 않음)이 없으면 가독성이 향상됩니다.
저스틴 존슨

5

... 더 많은 범위, 생성기 기능 사용.

function range(s, e, str){
  // create generator that handles numbers & strings.
  function *gen(s, e, str){
    while(s <= e){
      yield (!str) ? s : str[s]
      s++
    }
  }
  if (typeof s === 'string' && !str)
    str = 'abcdefghijklmnopqrstuvwxyz'
  const from = (!str) ? s : str.indexOf(s)
  const to = (!str) ? e : str.indexOf(e)
  // use the generator and return.
  return [...gen(from, to, str)]
}

// usage ...
console.log(range('l', 'w'))
//=> [ 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w' ]

console.log(range(7, 12))
//=> [ 7, 8, 9, 10, 11, 12 ]

// first 'o' to first 't' of passed in string.
console.log(range('o', 't', "ssshhhooooouuut!!!!"))
// => [ 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 't' ]

// only lowercase args allowed here, but ...
console.log(range('m', 'v').map(v=>v.toUpperCase()))
//=> [ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V' ]

// => and decreasing range ...
console.log(range('m', 'v').map(v=>v.toUpperCase()).reverse())

// => ... and with a step
console.log(range('m', 'v')
          .map(v=>v.toUpperCase())
          .reverse()
          .reduce((acc, c, i) => (i % 2) ? acc.concat(c) : acc, []))

// ... etc, etc.

이것이 유용하기를 바랍니다.


5

내 코드 골프 동료가 이것을 포함하여 (ES6) 생각해 냈습니다.

(s,f)=>[...Array(f-s+1)].map((e,i)=>i+s)

비 포함 :

(s,f)=>[...Array(f-s)].map((e,i)=>i+s)


4

d3에는 내장 범위 기능도 있습니다. https://github.com/mbostock/d3/wiki/Arrays#d3_range 참조 하십시오 :

d3.range ([시작,] 중지 [, 단계])

Python 내장 범위와 유사한 산술 진행을 포함하는 배열을 생성합니다. 이 방법은 배열의 인덱스와 같은 숫자 또는 정수 값 시퀀스를 반복하는 데 자주 사용됩니다. Python 버전과 달리 인수는 정수일 필요는 없지만 부동 소수점 정밀도로 인한 결과는 더 예측 가능합니다. 단계를 생략하면 기본값은 1입니다.

예:

d3.range(10)
// returns [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

나는 D3가 존재한다는 것을 몰랐다. 범위 방법을 사용하지 않지만이 패키지를 사용합니다.
mjwrazor

정말 고맙습니다. 나는 D3을 사용하고 있으며, D3이 이미 제공하고 있다는 것을 모르고 네이티브 JS 메소드를 찾고 있었다.
cezar

4

range ([start,] stop [, step]) 서명을 사용하여 완벽한 ES6 구현 :

function range(start, stop, step=1){
  if(!stop){stop=start;start=0;}
  return Array.from(new Array(int((stop-start)/step)), (x,i) => start+ i*step)
}

자동 네거티브 스테핑을 원하면

if(stop<start)step=-Math.abs(step)

또는 더 최소한으로 :

range=(b, e, step=1)=>{
  if(!e){e=b;b=0}
  return Array.from(new Array(int((e-b)/step)), (_,i) => b<e? b+i*step : b-i*step)
}

파울로 모레티의 발전기 접근 방식이 넓은 범위라면


교체 !stoptypeof stop === 'undefined', 다음 교체 intMath.floor하고, 검사를 추가 if (start > stop && step > 0)(그렇지 않으면 range(-3, -10)대신 두 단계의 부호를 틀지 또는 반환 (뭔가 제정신을하는 예외를 throw [])). 그렇지 않으면 좋습니다!
Ahmed Fasih

4

이에 대한 npm 모듈 bereich 가 있습니다 ( "bereich"는 "range"에 대한 독일어 단어입니다). 최신 JavaScript 반복자를 사용하므로 다음과 같은 다양한 방법으로 사용할 수 있습니다.

console.log(...bereich(1, 10));
// => 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

const numbers = Array.from(bereich(1, 10));
// => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

for (const number of bereich(1, 10)) {
  // ...
}

또한 내림차순 범위 (간단히 교환 minmax)를 지원하며 이외의 단계도 지원합니다 1.

면책 조항 : 나는이 모듈의 저자이므로 소금 한알로 대답하십시오.


4

이것도 반대로 작동합니다.

const range = ( a , b ) => Array.from( new Array( b > a ? b - a : a - b ), ( x, i ) => b > a ? i + a : a - i );

range( -3, 2 ); // [ -3, -2, -1, 0, 1 ]
range( 1, -4 ); // [ 1, 0, -1, -2, -3 ]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.