Python range ()와 유사한 JavaScript 함수


96

JavaScript에 Python과 유사한 함수가 range()있습니까?

매번 다음 줄을 쓰는 것보다 더 좋은 방법이 있어야한다고 생각합니다.

array = new Array();
for (i = 0; i < specified_len; i++) {
    array[i] = i;
}

1
@clwen : 안타깝게도 그게 없지만 내 코드를 살펴보세요 range(). Python에서 작동 하는 방식을 에뮬레이트하는 것을 목표로하는 함수를 작성 했으므로 사용할 수 있습니다. JavaScript에는 이러한 기능이 없지만 RangeMooTools 클래스 와 같은 다른 프레임 워크 용 플러그인이 있습니다 .
Tadeck

답변:


89

아니요 , 아무것도 없지만 만들 수 있습니다 .

JavaScript의 Python 구현 range()

Python 에서 작동하는 방식모방 하려고 하면 다음과 유사한 함수를 만들 수 있습니다.

function range(start, stop, step) {
    if (typeof stop == 'undefined') {
        // one param defined
        stop = start;
        start = 0;
    }

    if (typeof step == 'undefined') {
        step = 1;
    }

    if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
        return [];
    }

    var result = [];
    for (var i = start; step > 0 ? i < stop : i > stop; i += step) {
        result.push(i);
    }

    return result;
};

증거는 이 jsfiddle 을 참조하십시오 .

range()JavaScript와 Python의 비교

다음과 같은 방식으로 작동합니다.

  • range(4)반환 [0, 1, 2, 3],
  • range(3,6)반환 [3, 4, 5],
  • range(0,10,2)반환 [0, 2, 4, 6, 8],
  • range(10,0,-1)반환 [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
  • range(8,2,-2)반환 [8, 6, 4],
  • range(8,2)반환 [],
  • range(8,2,2)반환 [],
  • range(1,5,-1)반환 [],
  • range(1,5,-2)반환 [],

그리고 파이썬 대응 은 정확히 같은 방식으로 작동합니다 (적어도 언급 된 경우) :

>>> range(4)
[0, 1, 2, 3]
>>> range(3,6)
[3, 4, 5]
>>> range(0,10,2)
[0, 2, 4, 6, 8]
>>> range(10,0,-1)
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> range(8,2,-2)
[8, 6, 4]
>>> range(8,2)
[]
>>> range(8,2,2)
[]
>>> range(1,5,-1)
[]
>>> range(1,5,-2)
[]

따라서 Python과 유사하게 작동하는 함수가 필요한 경우 range()위에서 언급 한 솔루션을 사용할 수 있습니다.


4
몇 가지 추가 방어 검사를 수행 할 수 있습니다. 전달 된 인수가 모두 숫자에 강요되는지 확인하고 그 stop값이보다 큰지 확인합니다 start(그렇지 않은 경우 교체).
Russ Cam

1
@RussCam : 이것을 지적 해 주셔서 감사합니다. 유형 등에 대한 방어 검사를 추가하지는 않았지만 요소의 역순을 구현했습니다. 이제 마지막 매개 변수가 음의 정수일 때 Python 대응과 정확히 동일하게 작동합니다.
Tadeck 2011

@RussCam : start >= stop목표가 실제로 Python의 범위를 에뮬레이트하는 경우 빈 배열로 이어지는 것이 필요합니다. 어쨌든 더 직관적이라고 생각합니다.

1
@delnan : 체크는 더 복잡 할 수 있습니다. start >= stop이 함수가 range()파이썬 에서처럼 동작하기에는 간단 하지 않기 때문 입니다. 내 답변을 업데이트했습니다.
Tadeck

@delnan-Python 구현에 익숙하지 않습니다. 파이썬 구현에 익숙한 친구들 만 사용한다면 에뮬레이트하는 것이 합리적
Russ Cam

125

ES6의 매우 간단한 범위 :

let range = n => Array.from(Array(n).keys())

에서 bigOmega의 코멘트 , 이것은 사용 단축 할 수 확산 구문 :

let range = n => [...Array(n).keys()]

41
이것의 간단한 버전입니다let range = n => [...Array(n).keys()]
bigOmega

2
@BharathRaja 좋아요, 감사합니다! 왜 const가 아닌가? 나는 내가 할 수있는 곳에 const를 사용하려고 할 것이다 :) 자바 최종 대응 물처럼;)
Kjellski

당신 맞아요, 내가 사용하려고 const배열이 여전히 편집 될 수 있도록, 가능한 한, 그러나 여기 그냥 배열에 대한 참조 수 있습니다 : 'D
bigOmega

1
@bigOmega const반환 값이 아니라 함수 자체에 적용됩니다. 어떤 식 으로든 함수를 수정하고 싶지 않을 것입니다.
Solomon Ucko 19

7
이 대답은 시작 인덱스와 단계 크기를 늘리는 기능을 설명하지 않습니다.
Fluous

29

2018 :이 답변은 계속 찬성 투표를 받고 있으므로 여기에 업데이트가 있습니다. 아래 코드는 더 이상 사용되지 않지만 운 좋게도 ES6는 생성기와 yield키워드를 표준화 했으며 모든 플랫폼에서 보편적으로 지원됩니다. lazy range()using 의 예는 여기yield 에서 찾을 수 있습니다 .


말했다 이미 무슨뿐만 아니라, 자바 스크립트 1.7+에 대한 지원 제공 반복자 및 발전기 의 게으른, 메모리 효율적인 버전 만드는 데 사용할 수 있습니다 range에 simlar을 xrangePython2의를 :

function range(low, high) {  
    return {
        __iterator__: function() {
            return {  
                next: function() {
                    if (low > high)
                        throw StopIteration;  
                    return low++;
                }
            }
        }
    }
}

for (var i in range(3, 5))  
  console.log(i); // 3,4,5

1
+1 좋은 아이디어! 또한 step인수 를 구현 하고 내 대답 의 값에 대해 테스트 할 수 있습니까? 귀하의 답변은 매우 구체적인 브라우저를 염두에두고있는 애플리케이션에 적합합니다 (9 이전의 Chrome, Safari 및 IE 버전에서는 작동하지 않습니다. stackoverflow.com/a/2209743/548696 ).
Tadeck

@Tadeck : 아이러니하게도 최근에 매우 유사한 질문 을했는데, 확인해보세요. 좋은 답변이 있습니다. BTW, 귀하의 코드는 내 테스트를 통과하지 못했습니다. (
georg

테스트 데이터와 예상 결과를 공유 할 수 있습니까? 개선 할 수 있으면 좋겠지 만 내 테스트는 100 % 통과했습니다. 내가 제공 한 코드 가이 질문에 배치 한 스크립트에 의해 제대로 구문 분석되지 않았다고 말하는 것 입니까? stackoverflow.com/q/12173856/548696 ?
Tadeck 2012 년

@Tadeck : 신경 쓰지 마세요. 슬라이스를 테스트했으며 코드는 범위입니다.
georg

1
Python range에는 "마지막"값이 제외되어 있습니다 (따라서 위 코드 >=대신 사용해야 함 >)
Pac0

23

@Tadeck@georg의 두 답변을 결합 하여 다음 과 같이 생각해 냈습니다.

function* range(start, stop, step = 1) {
    if (stop == null) {
        // one param defined
        stop = start;
        start = 0;
    }

    for (let i = start; step > 0 ? i < stop : i > stop; i += step) {
        yield i;
    }
}

for 루프에서 사용하려면 ES6 / JS1.7 for-of 루프가 필요합니다.

for (let i of range(5)) {
    console.log(i);
}
// Outputs => 0 1 2 3 4

for (let i of range(0, 10, 2)) {
    console.log(i);
}
// Outputs => 0 2 4 6 8

for (let i of range(10, 0, -2)) {
    console.log(i);
}
// Outputs => 10 8 6 4 2

ES6를 사용하는 경우 기본 매개 변수를 사용하지 않는 이유는 무엇 입니까?
Amin NAIRI

@Gradiuss 그것은 작동 할 step매개 변수 만하면 stop, 모두 전달되지 startstop필요 변경 될 수 있습니다. 나는 그것을 업데이 트됩니다
janka102

2
WTG, 이것은 지금까지 제시된 최고의 구현입니다. 생성기를 사용하며 (전체 시퀀스를 메모리에 저장할 필요가 없기 때문에 좋음) 매우 간결합니다.
루시오 PAIVA

undefined는 null과 같은 객체에 대한 포인터입니다. 다음과 같이 3 개의 등호와 비교할 수 있습니다. if (stop === undefined) {3 개의 등호는 자동 캐스팅없이 비교됩니다. 비교 유형도 그대로 비교하십시오. 2 개의 등호는 자동 캐스팅과 다른면 유형과 비교됩니다.
Shimon Doodkin 2018 년

20

rangePython 2 의 함수 포트는 underscore.jslodash 유틸리티 라이브러리 (다른 많은 유용한 도구와 함께)에서 제공됩니다. 밑줄 문서에서 복사 한 예 :

_.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]
_.range(0);
=> []

15

Number프로토 타입에 반복자를 연결하여 달성 할 수 있습니다.

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

[...5] // will result in [0,1,2,3,4,5]

Kyle Simpson의 비동기 JavaScript 재검토 과정에서 발췌


7
이것은 정말 멋지지만, 프로토 타입을 재정의하는 것은 너무 취약합니다. '(
m0meni

8

범위의 시작 위치와 끝 위치를 모두 지정해야하는 경우 답변 중 하나에 대한 작은 확장이 있습니다.

let range = (start, end) => Array.from(Array(end + 1).keys()).slice(start);

7

여기 있습니다.

이것은 인덱스 번호로 각 인덱스의 값을 쓰거나 덮어 씁니다.

Array.prototype.writeIndices = function( n ) {
    for( var i = 0; i < (n || this.length); ++i ) this[i] = i;
    return this;
};

숫자를 제공하지 않으면 배열의 현재 길이를 사용합니다.

다음과 같이 사용하십시오.

var array = [].writeIndices(10);  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

5

size 배열을 얻으려면 x라이브러리를 사용하지 않고 한 줄짜리가 있습니다.

var range = n => Array(n + 1).join(1).split('').map((x, i) => i)

로 작동

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

2
var range = n => Array(n).fill().map((e, i) => i);
Valen

x실제로 n매개 변수 이름으로 사용했을 때 '크기 ' 라고 말하는 이유
Valen

5

다음은 Python의 range () 함수를 JavaScript에 자연스럽게 적용한 것입니다 .

// Generate range from start (inclusive) to stop (exclusive):
function* range(start, stop, step = 1) {
   if (stop === undefined) [start, stop] = [0, start];
   if (step > 0) while (start < stop) yield start, start += step;
   else if (step < 0) while (start > stop) yield start, start += step;
   else throw new RangeError('range() step argument invalid');
} 

// Examples:
console.log([...range(3)]);       // [0, 1, 2]
console.log([...range(0, 3)]);    // [0, 1, 2]
console.log([...range(0, 3, -1)]);// []
console.log([...range(0, 0)]);    // []
console.log([...range(-3)]);      // []
console.log([...range(-3, 0)]);   // [-3, -2, -1]

그것은에 비교 될 수있는 인수 지원 0stop에 의해 증가 될 수 있습니다 step. 를 초과하지 않는 숫자와 함께 사용할 때 Python 버전과 동일하게 작동합니다 Number.MAX_SAFE_INTEGER.

다음 코너 케이스에 유의하십시오.

[...range(0, 0, 0)];        // RangeError: range() step argument invalid
[...range(Number.MAX_SAFE_INTEGER + 1, Number.MAX_SAFE_INTEGER + 2)];  // []
[...range(Number.MAX_SAFE_INTEGER + 2, Number.MAX_SAFE_INTEGER + 3)];  // Infinite loop
[...range(0.7, 0.8, 0.1)];  // [0.7, 0.7999999999999999]
[...range('1', '11')];      // ['1']
[...range('2', '22')];      // Infinite loop

대조적 @ Tadeck의 , Volv의 @@ janka102의 대답하는 창 [], undefined혹은 때 무한 루프를 입력 step들을 평가가 0또는 NaN이 함수 발생기 파이썬의 동작과 유사 예외를 던진다.


동의합니다. 다른 답변은 고유 한 방식으로 우아하지만이 접근 방식과 기능은 훨씬 비단뱀 적입니다.
Travis Clarke

4

ES6 기본 매개 변수로 더욱 개선되었습니다.

let range = function*(start = 0, stop, step = 1) {
  let cur = (stop === undefined) ? 0 : start;
  let max = (stop === undefined) ? start : stop;
  for (let i = cur; step < 0 ? i > max : i < max; i += step)
    yield i
}

이것이 범위가 실제로 보이는 방식입니다.
Konrad Linkowski

4

pythonicrangeJS 생성기 ( yield)를 사용하여 Python 동작을 가장 잘 모방하여 range(stop)range(start, stop, step)사용 사례를 모두 지원합니다 . 또한 pythonicrange함수는 Iterator및를 지원하는 Python과 유사한 객체를 반환 하므로 다음 mapfilter같은 멋진 한 줄짜리 작업을 수행 할 수 있습니다.

import {range} from 'pythonic';
// ...
const results = range(5).map(wouldBeInvokedFiveTimes);
// `results` is now an array containing elements from
// 5 calls to wouldBeInvokedFiveTimes

다음을 사용하여 설치 npm:

npm install --save pythonic

공개 저는 Pythonic의 작성자이자 관리자입니다.


3

MDN은 다음 접근 방식을 권장합니다. 시퀀스 생성기 (범위)

// Sequence generator function (commonly referred to as "range", e.g. Clojure, PHP etc)
const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));

// Generate numbers range 0..4
console.log("range(0, 4, 1):", range(0, 4, 1));
// [0, 1, 2, 3, 4] 

// Generate numbers range 1..10 with step of 2 
console.log("\nrange(1, 10, 2):", range(1, 10, 2));
// [1, 3, 5, 7, 9]

// Generate the alphabet using Array.from making use of it being ordered as a sequence
console.log("\nrange('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x))", range('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x)));
// ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]


2

밑줄 라이브러리를 사용할 수 있습니다 . 배열 작업에 유용한 수십 가지 기능이 포함되어 있습니다.


2

JavaScript에 Python의 range ()와 유사한 함수가 있습니까?

여기에있는 모든 솔루션은 Python 2의 범위를 참조합니다 (아마도 제공 한 코드 예제 때문일 수 있음). 그러나 Python 3에서 range () 메서드는 반복자를 반환합니다. JavaScript에는 또한 반복기가 있으며 전체 배열을 생성하여 메모리에 저장하는 것보다 공간 효율적입니다.

따라서 Python 3의 range(n)함수를 보다 정확하게 표현하면 Array(n).keys().

예를 들면 :

for (let i of Array(n).keys()) {
  console.log(i) // 0, 1, 2, 3, ..., n
}

하나 더 예 (이미 다른 답변에서 다뤘습니다). 반복기를 배열로 변환 (ES6) :

let ary = [...Array(n).keys()];
// ary = [0, 1, 2, 3, ..., n]

1

여전히에 상응하는 내장 함수는 range()없지만 최신 버전 인 ES2015를 사용하면 자체 구현을 빌드 할 수 있습니다. 여기에 제한된 버전이 있습니다. 단계 매개 변수를 고려하지 않기 때문에 제한됩니다. 최소, 최대.

const range = (min = null, max = null) =>
  Array.from({length:max ? max - min : min}, (v,k) => max ? k + min : k)

이는 속성 Array.from이있는 모든 객체에서 배열을 만들 수 있는 메서드에 의해 수행됩니다 length. 따라서 length속성 만있는 간단한 개체를 전달하면 개체 수를 생성하는 ArrayIterator가 생성 length됩니다.


1

이것이 내가 선호하는 방법입니다. Python에서와 같이 하나 또는 두 개의 입력을 지정할 수 있습니다.

function range(start, end) {
  return Array.from(Array(end||start).keys()).slice(!!end*start)
}

0

다음은 es6범위의 또 다른 구현입니다.

// range :: (from, to, step?) -> [Number]
const range = (from, to, step = 1) => {
  //swap values if necesery
  [from, to] = from > to ? [to, from] : [from, to]
  //create range array
  return [...Array(Math.round((to - from) / step))]
    .map((_, index) => {
      const negative = from < 0 ? Math.abs(from) : 0
      return index < negative ? 
        from + index * step  :
        (index - negative + 1) * step
    })
}  

range(-20, 0, 5)
  .forEach(val => console.log(val))

for(const val of range(5, 1)){
   console.log(`value ${val}`)
}


에서 -20까지 배열을 생성 하려면 -30어떻게 해야 합니까?
Amin NAIRI

흠, 이것은 -30에서 -20까지 배열을 생성하지만 원하는 경우 리버스 속성을 포함하도록 쉽게 수정할 수 있습니다. 나는 그것을 포함 위의 대답을 편집합니다
mrFunkyWisdom

0

아니요, 아무것도 없지만 만들 수 있습니다.

범위의 Python3 동작에 부분적입니다. 아래에서 JavaScript의 Python range () 구현을 찾을 수 있습니다.

function* range(start=0, end=undefined, step=1) {    
    if(arguments.length === 1) {end = start, start = 0}    
    
    [...arguments].forEach(arg => {    
        if( typeof arg !== 'number') {throw new TypeError("Invalid argument")}                               
    })    
    if(arguments.length === 0) {throw new TypeError("More arguments neede")}    
        
    if(start >= end) return                                                                                                                                     
    yield start    
    yield* range(start + step, end, step)    
}    
         
// Use Cases
console.log([...range(5)])

console.log([...range(2, 5)])

console.log([...range(2, 5, 2)])
console.log([...range(2,3)])
// You can, of course, iterate through the range instance.


0

단일 단계로 간단한 범위가 필요하다고 가정합니다.

let range = (start, end)=> {
    if(start === end) return [start];
    return [start, ...range(start + 1, end)];
}

그밖에

let range = (start, end, step)=> {
    if(start === end) return [start];
    return [start, ...range(start + step, end)];
}

자세한 내용은 여기 를 참조하십시오 .


0

JavaScript에 Python의 range ()와 유사한 함수가 있습니까?

이전에 대답했듯이 : 아니오 , 없습니다. 하지만 직접 만들 수 있습니다. 저는 이것이 ES6에 대한 흥미로운 접근 방식이라고 생각합니다. Python 2.7과 매우 유사하게 작동 range()하지만 훨씬 더 동적입니다.

function range(start, stop, step = 1) 
{
    // This will make the function behave as range(stop)
    if(arguments.length === 1)
    {
        return [...Array(arguments[0]).keys()]
    }

    // Adjusts step to go towards the stop value
    if((start > stop && !(step < 0)) ||
       (start < stop && !(step > 0)))
    {
        step *= -1
    }

    let returnArray = []
    // Checks if i is in the interval between start and stop no matter if stop
    // is lower than start or vice-versa
    for(let i = start; (i-start)*(i-stop) <= 0; i += step)
    {
        returnArray.push(i)
    }
    return returnArray
}

이 함수는 세 가지 다른 방식으로 작동 할 수 있습니다 (파이썬의 range ()처럼) :

  1. range(stop)
  2. range(start, stop)
  3. range(start, stop, step)

이러한 예 :

console.log(range(5))
console.log(range(-2, 2))
console.log(range(2, -2))
console.log(range(10, 20, 2))

다음과 같은 출력이 제공됩니다.

[ 0, 1, 2, 3, 4 ]
[ -2, -1, 0, 1, 2 ]
[ 2, 1, 0, -1, -2 ]
[ 10, 12, 14, 16, 18, 20 ]

in연산자 (예 : python)로 배열을 반복하는 대신 of. 따라서 i변수는 배열 요소의 인덱스가 아닌 값을 가정합니다.

for(let i of range(5))
{
    // do something with i...
}

0

NodeJ에 대한 옵션은 버퍼를 사용하는 것입니다.

[...Buffer.alloc(5).keys()]
// [ 0, 1, 2, 3, 4 ]

좋은 점은 버퍼에서 직접 반복 할 수 있다는 것입니다.

Buffer.alloc(5).forEach((_, index) => console.log(index))
// 0
// 1
// 2
// 3
// 4

초기화되지 않은 배열로는이를 수행 할 수 없습니다.

Array(5).forEach((_, index) => console.log(index))
// undefined

그러나 올바른 마음으로 이와 같은 목적으로 버퍼를 사용하는 사람;)


-1

방법은 다음과 같습니다.

let n = 5 
[...Array(n).keys()].map(x=>{console.log(x)})

산출

0
1
2
3
4

단계를 지원하지 않습니다.
Mark Stosberg
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.