JavaScriptには、指定された範囲内で範囲を生成するための「range()」のようなメソッドがありますか?


872

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']これは、質問の2番目の部分で見つけることができる最も近いものです。
Andrew_1510 2016年

Andrew_1510 @あなたは使用することができますsplit("")もあり
アレックス

1
恋人バインドされているが、このonelinerをゼロ:Array.apply(null, { length: 10 }).map(eval.call, Number)
csharpfolk

回答:


1501

数字

[...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()]);

(ES6はnil petersohnと他のコメント者へのクレジット)


72
それがどこでも役に立つなら、それはおそらくJSで役に立つからです。(JSは関数型プログラミングタイプのものを実行できます。これは、範囲(0ステートメント。それと、その他の1000の理由で、いくつかのまれなケースで役立つかもしれません)
Lodewijk

5
単純に使用して(new Array(5)).map(function (value, index) { return index; })もうまくいかない理由はありますか?これは[undefined × 5]Chrome DevToolsに戻ります。
ルイス、

12
@Lewisこれで定義された配列には空のスロットがありmap()、その友人やその友人の1人と繰り返し処理されません。
アレックス

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

17
Array(5).fill()もマッピング可能です
nils petersohn 2017年

333

数値には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)
スチュコックス

2
@Delapouite素晴らしい!あなたはそれを別の答えにするべきです、そして私はそれに投票します!これは、この複製に対する完璧な答えでもあります。
ジブ

9
@Delapouite @jibそして、これも:Array.from({length: end - start}, (v, k) => k + start)
Aditya Singh

1
@ icc97はい、リンターは文句を言うかもしれませんが、JavaScriptではを渡すことと同じであると定義された関数引数を省略している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 FYI:あなたの例は間違っています。stop実際には停止/終了位置ではなく、カウント/距離です。(違反はなく、タイプミスを人々に知らせるだけです)
F Lekschas '26 / 07/26

4
混乱した人のために-F Lekschasのコメントの後のrodfersouの編集により、彼のコードは現在正しいです。
エドラ

1
に渡す引数Array(Math.ceil((stop - start) / step) + 1)は、+1phpの「包括的」動作を実際に模倣するために、最後にが必要です。
ヨハンデットマー

3
これは、rangeメソッドを完全に実装するJavaScript関数の完全な質問に実際に答える一番上の答えです。現在これを超える他のすべて(lodashを除く_.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 2018年

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;
}

stopeg で定義されているよりも高い値を削除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 2015

1
これはstep != 1while条件を考慮する必要がある場合は機能しませんstep。デフォルトstep値で更新したバージョン:function range(start、stop、step){step = step || 1 var a = [start]、b = start; while((b + step)<stop){console.log( "b:" + b + "。a:" + a + "。"); b + =ステップ; a.push(b); }を返す; }
daveharris '25年

@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、未定義、NaN、ブール、配列、オブジェクトなどの場合、このメソッドは次のエラーを返しますundefined method toUpperCase to etc
ビクター

`` `if(typeof from!== 'number' && typeof from!== 'string'){throw new TypeError( '最初のパラメータは数値または文字でなければなりません')} if(typeof to!== ' number '&& typeof to!==' string '){throw new TypeError('最初のパラメーターは数値または文字でなければなりません ')} `` `
Victor

36

OK、 JavaScriptにはPHPのrange()ような関数がないので、簡単に作成できる関数を作成する必要があります。1行の関数をいくつか作成し、数字アルファベットで次のように分けます。

以下のための数字

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
これらの関数には1つずれたエラーがあると思います。である必要がArray(end - start + 1)ありArray(end.charCodeAt(0) - start.charCodeAt(0) + 1)ます。
外耳道

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]

お役に立てれば幸いです。


そして、これがどのように機能するかです。

基本的に私は最初に結果の配列の長さを計算し、その長さにゼロで満たされた配列を作成し、次に必要な値でそれを満たします

  • (step || 1)=>そして、このような他のものは、の値を使用することを意味し、stepそれが提供されなかった場合は1代わりに使用します
  • を使用(Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1)して結果配列の長さをより簡単に計算することから始めます (方向/ステップの両方の差*オフセット)
  • 長さを取得した後、ここでチェックを使用して初期化された値を持つ空の配列を作成し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
確かに便利です。簡単?失礼ですが同意できません; あなたがそれをワンライナーにするかどうかにかかわらず。Pythonから来るのはショックです。
PascalVKooten 2016年

@PascalvKooten、ええもちろん、Pythonのような組み込みのメソッドがあったらいいと思いますが、これは私が手に入れられる最も簡単な方法でした。そして、それは私のプロジェクトで便利であることが証明されています。
azerafati 2016

そのように苦痛なほど複雑なコードスニペットを、特にワンライナーとして、どのように機能するかの説明なしで投稿しますか?「うまくいく」かどうかに関係なく、良い SOの答えの悪い例。
Madbreaks 16

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 16


18

Harmony スプレッド演算子と矢印関数の使用:

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

この場合、下線「_」記号は何を表していますか?
Oleh Berehovskyi

@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
Just const range = (x, y) => Array.from(function* () { while (x <= y) yield x++; }())
lokhmakov

@lokhmakovはい、そうです。ありがとうございました!私の答えにあなたのコードを適用しただけです。
Hero Qu

15

いくつかのさまざまな範囲関数について調査しました。 これらの機能を実行するさまざまな方法のjsperf比較確認してください。確かに完全なリストでも網羅的なリストでもありませんが、役立つはずです:)

勝者は...

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

技術的には、Firefoxの最速ではありませんが、Chromeのクレイジーな速度の違い(imho)がそれを補います。

これらの配列関数では、FirefoxよりもChromeの方がはるかに高速です。Chromeは少なくとも4倍または5倍高速です。


これは、ステップサイズパラメーターを含む範囲関数と比較されたことに注意してください
binaryfunt

15

標準のJavaScriptには、範囲を生成するための組み込み関数がありません。いくつかのJavaScriptフレームワークは、そのような機能のサポートを追加します。または、他の人が指摘したように、いつでも独自のものをロールバックできます。

再確認したい場合、最も信頼できるリソースはECMA-262 Standardです。


私は2010年に完全に良い答えだと確信していますが、これはもはや最善のアプローチと見なされるべきではありません。prototype.jsのは👍行う傾向にあったようにあなたは、種類に建て延びているべきではない
ダナウッドマン

@DanaWoodmanこれを提供してくれてありがとう-それは確かに2018年にはかなり時代遅れになっているので、Prototype.jsへの参照を削除するように答えを更新しました
Mike Dinescu

21
まあ、これはまったく役に立ちませんでした。
ピティコ

@Pithikosこの質問は最初に質問されてから編集されており、OPはJSにネイティブの範囲関数があるかどうかを知りたがっています。
Mike Dinescu

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、2015年

ただし、ループの外で使用すると、ジェネレーターが少し奇妙になります。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 2017

10

これは最善の方法ではないかもしれません。しかし、1行のコードで一連の数値を取得する場合は、例: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]

Pythonの範囲と同様に動作します。

>>> 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()は一種の「強化された」機能を作成した要点を作成しました。特に、上記のベアボーンバリアントでは対処できない可能性があるエッジケースをキャプチャすることを目的としました。さらに、英数字の範囲のサポートを追加しました。換言すれば、2つの付属のような入力とそれを呼び出す'C''K'(この順序では)値文字「K」(排他的)を介して、文字「C」(含む)から文字の連続集合である配列を返す: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からではなくrangePythonからの模倣です

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の配列で3ミリ秒かかり、2位は13ミリ秒で、IDEの赤い線が表示されます。
mjwrazor

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、ありがとうございます。そうです、ループの各パスで「開始」パラメーターをインクリメントするのを忘れていました。現在は修正されています。
jhaskell 2015年

それでも目的の出力は生成されません。5〜10の範囲が必要な場合は、が表示されます[5, 6, 7, 8, 9, 10, 11, 12, 13, 14]。その配列の前半のみを期待します。
アレックス

@alex、ありがとうございます。入力に基づく長さの制約は考慮していませんでした。更新されたバージョンを参照してください。
jhaskell

6

IE11を除くすべてのブラウザーサポートされているHarmonyジェネレーターの使用:

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節に三項演算(特にネストされていない)がないと、ここで読みやすくなります。
Justin Johnson

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バージョンとは異なり、引数は整数である必要はありませんが、浮動小数点の精度が原因である場合、結果はより予測可能です。stepを省略すると、デフォルトで1になります。

例:

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

D3の存在を知りませんでした。それらの範囲メソッドを使用する予定はありませんが、このパッケージを使用します。
mjwrazor

どうもありがとうございます。私はD3を使用していて、ネイティブのJSメソッドを探していましたが、D3がすでに提供していることを知りませんでした。
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)
}

あなたが巨大な範囲を持っているなら、Paolo Morettiのジェネレーターアプローチを見てください


交換する!stoptypeof stop === 'undefined'、その後置き換えintMath.floor、チェックを追加しますif (start > stop && step > 0)(そうでない場合は、range(-3, -10)代わりに、いずれかのステップの符号を反転させるか、返す(何かの正気を行うための例外をスロー[]))。そうでなければ、いいね!
Ahmed Fasih、2016

4

そのためのnpmモジュールbereichがあります(「bereich」は「範囲」のドイツ語です)。最新の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

免責事項:私はこのモジュールの作成者です。ですから、私の答えを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.