webentwicklung-frage-antwort-db.com.de

Verfügt JavaScript über eine Methode wie "range ()", um einen Bereich innerhalb der angegebenen Grenzen zu generieren?

In PHP können Sie ...

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

Das heißt, es gibt eine Funktion, mit der Sie einen Zahlen- oder Zeichenbereich erhalten, indem Sie die oberen und unteren Grenzen übergeben.

Gibt es etwas, das nativ in JavaScript integriert ist? Wenn nicht, wie würde ich es implementieren?

549
alex

Es funktioniert für Zeichen und Zahlen, mit einem optionalen Schritt vorwärts oder rückwärts.

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 .

Wenn Sie native Typen erweitern möchten, weisen Sie sie Array.range zu.

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;

}

console.log(range("A", "Z", 1));
console.log(range("Z", "A", 1));
console.log(range("A", "Z", 3));


console.log(range(0, 25, 1));

console.log(range(0, 25, 5));
console.log(range(20, 5, 5));

63
alex

Zahlen

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

Zeicheniteration

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

Iteration

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"

Als Funktionen

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

Als getippte Funktionen

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() function

_.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"

Alte, nicht es6-fähige Browser ohne Bibliothek:

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

Vielen Dank.

(ES6 Kredit an Nil Petersohn und andere Kommentatoren)

1124
Ben

Für Zahlen können Sie ES6 verwenden Array.from(), was heutzutage in allem funktioniert außer IE:

Kürzere Version:

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

Längere Version:

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

dadurch wird ein Array von 0 bis einschließlich 19 erstellt. Dies kann zu einer dieser Formen weiter verkürzt werden:

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

Es können auch untere und obere Grenzen angegeben werden, zum Beispiel: 

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

Ein Artikel, der dies ausführlicher beschreibt: http://www.2ality.com/2014/05/es6-array-methods.html

250
CapK

Hier sind meine 2 Cent:

    function range(start, count) {
      return Array.apply(0, Array(count))
        .map(function (element, index) { 
          return index + start;  
      });
    }
88
jflood.net

Mein neues Lieblingsformular ( ES2015 )

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

Und wenn Sie eine Funktion mit einem step param benötigen:

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

einfache Bereichsfunktion:

function range(start, stop, step){
  var a=[start], b=start;
  while(b<stop){b+=(step || 1);a.Push(b)}
  return a;
};
37
Remi
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']
34
kennebec

OK, in JavaScript haben wir keine range()-Funktion wiePHP, also müssen wir die Funktion erstellen, was ziemlich einfach ist, ich schreibe ein paar einzeilige Funktionen für Sie und trenne sie Sie für Nummern und Alphabete wie unten:

für Nummern :

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

und nennen Sie es wie:

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

für Alphabete :

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

und nennen Sie es wie:

alphabetRange('c', 'h'); //["c", "d", "e", "f", "g"]
33
Alireza
var range = (l,r) => new Array(r - l).fill().map((_,k) => k + l);
23
Artur Klesun

Praktische Funktion, um den Trick zu machen, führen Sie den folgenden Code-Ausschnitt aus

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

hier ist, wie man es benutzt

Bereich (Start, Ende, Schritt = 1, Versatz = 0);

  • inclusive - forward range(5,10) // [5, 6, 7, 8, 9, 10]
  • inklusive - rückwärts range(10,5) // [10, 9, 8, 7, 6, 5]
  • schritt zurück range(10,2,2) // [10, 8, 6, 4, 2]
  • exclusive - forward range(5,10,0,-1) // [6, 7, 8, 9] not 5,10 themselves
  • offset - expand range(5,10,0,1) // [4, 5, 6, 7, 8, 9, 10, 11]
  • offset - verkleinern range(5,10,0,-2) // [7, 8]
  • schritt - erweitere range(10,0,2,2) // [12, 10, 8, 6, 4, 2, 0, -2]

ich hoffe, Sie finden es nützlich.


Und so funktioniert es.

Grundsätzlich berechne ich zuerst die Länge des resultierenden Arrays und erstelle ein mit Null gefülltes Array mit dieser Länge und fülle es dann mit den erforderlichen Werten

  • (step || 1) => Und andere wie diese verwenden den Wert von step, und wenn er nicht angegeben wurde, verwenden Sie stattdessen 1
  • Wir beginnen mit der Berechnung der Länge des Ergebnis-Arrays mit (Math.abs(end - start) + ((offset || 0) * 2)) / (step || 1) + 1), Um es einfacher zu machen (Differenz * Offset in beide Richtungen/Schritte).
  • Nachdem wir die Länge ermittelt haben, erstellen wir mit new Array(length).fill(0);hier prüfen ein leeres Array mit initialisierten Werten
  • Jetzt haben wir ein Array [0,0,0,..] Mit der gewünschten Länge. Wir ordnen es zu und geben ein neues Array mit den benötigten Werten zurück, indem wir Array.map(function() {}) verwenden.
  • var direction = start < end ? 1 : 0; Wenn start nicht kleiner als end ist, müssen wir uns natürlich rückwärts bewegen. Ich meine von 0 auf 5 oder umgekehrt
  • Bei jeder Iteration gibt uns startingPoint + stepSize * index den Wert, den wir benötigen
23
azerafati

Das Standard-Javascript verfügt nicht über eine integrierte Funktion zum Erzeugen von Bereichen. Mehrere Javascript-Frameworks bieten Unterstützung für solche Funktionen, oder, wie andere darauf hingewiesen haben, können Sie immer selbst eine Rolle spielen.

Wenn Sie noch einmal nachprüfen möchten, ist die endgültige Ressource der ECMA-262 Standard .

16
Mike Dinescu

Verwenden der Harmony Spread- Operator Pfeil-Funktionen:

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

Beispiel:

range(10, 15);
[ 10, 11, 12, 13, 14, 15 ]
14
c.P.u1

Hat einige Recherchen zu verschiedenen Range-Funktionen durchgeführt .Überprüfen Sie den jsperf-Vergleich der verschiedenen Möglichkeiten, diese Funktionen auszuführen. Sicherlich keine perfekte oder erschöpfende Liste, sollte aber helfen :)

Der Gewinner ist...

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

Technisch ist es nicht das schnellste auf Firefox, aber verrückter Geschwindigkeitsunterschied (imho) auf Chrom macht das wett.

Interessant ist auch, wie viel schneller Chrom mit diesen Array-Funktionen ist als Firefox. Chrome ist mindestens vier- oder fünfmal schneller.

11
Justin

Eine interessante Herausforderung wäre, die kürzeste Funktion zu schreiben. Rekursion zur Rettung!

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

Neigt dazu, bei großen Reichweiten langsam zu sein, aber zum Glück sind Quantencomputer gleich um die Ecke.

Ein zusätzlicher Bonus ist, dass es verschleiert ist. Weil wir alle wissen, wie wichtig es ist, unseren Code vor neugierigen Blicken zu verbergen.

Um die Funktion wirklich und vollständig zu verschleiern, führen Sie folgende Schritte aus:

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

Ich würde so etwas codieren:

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]

Es verhält sich ähnlich wie der Python-Bereich:

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

Eine andere Version mit ES6-Generatoren (siehe große Paolo Moretti antwortet mit ES6-Generatoren ):

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

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

Oder, wenn wir nur iterable brauchen, dann:

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

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

Sie können lodash oder Undescore.jsrange verwenden:

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

Wenn Sie alternativ nur aufeinanderfolgende ganze Zahlen benötigen, können Sie Folgendes tun:

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

In ES6 kann range mit Generatoren implementiert werden :

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

Diese Implementierung spart Speicherplatz beim Durchlaufen großer Sequenzen, da nicht alle Werte in einem Array verwirklicht werden müssen:

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

Eine eher minimalistische Implementierung, die ES6 stark verwendet, kann wie folgt erstellt werden, wobei die statische Methode Array.from() besonders hervorgehoben wird:

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

Dies ist zwar nicht aus PHP, sondern eine Imitation von range ausPython.

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] 
7
user642922

Verwenden von Harmony-Generatoren , von allen Browsern außer IE11 unterstützt :

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

Beispiele

take

Beispiel 1.

take braucht nur so viel wie es geht

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

kehrt zurück

[100, 105, 110, 115, 120]

Beispiel 2.

to nicht erforderlich

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

kehrt zurück

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

takeAll

Beispiel 3.

from nicht erforderlich

takeAll( range( {to: 5} ) )

kehrt zurück

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

Beispiel 4.

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

kehrt zurück

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

Beispiel 5.

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

kehrt zurück

["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"]

6
Janus Troelsen

sie können die lodash-Funktion _.range(10)https://lodash.com/docs#range verwenden.

5
lkan

... mehr Reichweite mit Generatorfunktion.

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.

Hoffe das ist nützlich.

5
John Swindin

Zum Erzeugen eines numerischen Arrays für einen bestimmten Bereich verwende ich Folgendes: 

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]

Offensichtlich funktioniert es nicht für alphabetische Arrays.

5
jhaskell

d3 hat auch eine eingebaute Range-Funktion. Siehe https://github.com/mbostock/d3/wiki/Arrays#d3_range :

d3.range ([start,] stop [ step])

Erzeugt ein Array mit einer arithmetischen Progression, ähnlich dem integrierten Python-Bereich. Diese Methode wird häufig verwendet, um eine Folge von numerischen oder ganzzahligen Werten, beispielsweise die Indizes in einem Array, zu durchlaufen. Im Gegensatz zur Python-Version müssen die Argumente keine Ganzzahlen sein, obwohl die Ergebnisse besser vorhersehbar sind, wenn sie auf die Gleitkomma-Genauigkeit zurückzuführen sind. Wenn Schritt weggelassen wird, ist der Standardwert 1. 

Beispiel:

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

Dafür gibt es ein npm-Modul bereich ("bereich" ist das deutsche Wort für "range"). Es verwendet moderne JavaScript-Iteratoren, so dass Sie es auf verschiedene Arten verwenden können, z.

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)) {
  // ...
}

Es unterstützt auch absteigende Bereiche (durch einfachen Austausch von min und max) und auch andere Schritte als 1.

Disclaimer: Ich bin der Autor dieses Moduls, bitte nehmen Sie meine Antwort mit einem Salzkorn.

4
Golo Roden

range(start,end,step): Mit ES6-Iteratoren

Sie fragen nur nach einer Ober- und Untergrenze. Hier erstellen wir auch einen Schritt.

Sie können einfach eine range()-Generatorfunktion erstellen, die als Iterator fungieren kann. Dies bedeutet, dass Sie nicht das gesamte Array vorab generieren müssen.

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

Jetzt können Sie etwas erstellen, das das Array vom Iterator vorgeneriert und eine Liste zurückgibt. Dies ist nützlich für Funktionen, die ein Array akzeptieren. Hierfür können wir Array.from() verwenden.

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

Jetzt können Sie einfach ein statisches Array erstellen,

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

Wenn jedoch ein Iterator gewünscht wird (oder Sie die Möglichkeit haben, einen Iterator zu verwenden), können Sie auch leicht einen erstellen.

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

Besondere Hinweise

4
Evan Carroll

Vollständige ES6-Implementierung mit Range ([Start,] Stop [ Schritt]) Signatur:

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

Wenn Sie ein automatisches negatives Stepping wünschen, fügen Sie hinzu

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

Oder eher minimalistisch:

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

Wenn Sie große Reichweiten haben, schauen Sie sich den Generatoransatz von Paolo Moretti an

4
Anona112

Keines der Beispiele hatte Tests, Implementierung für Schritt mit der Option, abnehmende Werte zu erzeugen.

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

}

Tests:

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

Sie können auch Folgendes tun:

const range = Array.from(Array(size)).map((el, idx) => idx+1).slice(begin, end);
3
gty3310

Ich war überrascht, auf diesen Thread zu stoßen und nichts wie meine Lösung zu sehen (vielleicht habe ich eine Antwort verpasst), also hier ist es .

// [begin, end[
const range = (b, e) => Array.apply(null, Array(e - b)).map((_, i) => {return i+b;});

Es funktioniert jedoch nur beim Vorwärtszählen (dh Anfang <Ende), sodass wir es bei Bedarf leicht modifizieren können: 

const range = (b, e) => Array.apply(null, Array(Math.abs(e - b))).map((_, i) => {return b < e ? i+b : b-i;});
3
nha

Hier ist ein schöner kurzer Weg, um es in ES6 nur mit Zahlen zu tun (weiß nicht, wie schnell die Geschwindigkeit ist)

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

Für eine Reihe einzelner Zeichen können Sie es leicht ändern:

Array.prototype.map.call(' '.repeat(1 + upper.codePointAt() - lower.codePointAt()), (v, i) => String.fromCodePoint(i + lower.codePointAt()));
3
Michael Plautz

Mein Codegolf-Mitarbeiter hat folgendes (ES6) erfunden:

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

nicht inklusive:

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

Dieser funktioniert auch umgekehrt.

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 ]
1
Rocco Ghielmini

Es gibt keine native Methode. Sie können dies jedoch mit der filter-Methode von Array tun.

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
jules3c

Für einen mehr Ruby-ähnlichen Ansatz mit guter Rückwärtskompatibilität:

range([begin], end = 0) wobei begin und end Zahlen sind

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

Beispiele:

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

Eine rekursive Lösung zum Generieren eines Integer-Arrays innerhalb von Grenzen.

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
Zack

Ich habe eine JS-Range-Funktion gefunden, die der in PHP entspricht, und funktioniert erstaunlich gut hier . Arbeitet vorwärts und rückwärts und funktioniert mit ganzen Zahlen, Floatern und Alphabeten!

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

Und hier ist die verminderte Version:

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
evilReiko

Sie können folgenden Einzeiler verwenden, um die Dinge kurz und einfach zu halten

var start = 4;
var end = 20;
console.log(Array(end - start + 1).fill(start).map((x, y) => x + y));
1
Rahul Vala

Hier ist meine Lösung, die Python nachahmt. Unten finden Sie einige Beispiele zur Verwendung. Es funktioniert mit Zahlen, genau wie Pythons 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;
}

Beispiele:

// 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
Jabba

Ich bevorzuge den Weg unten

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
Vivek Maru

Das ist was ich für Nummernbereiche verwende:

const rangeFrom0 = end => [...Array(end)].map((_, index) => index);

oder

const rangeExcEnd = (start, step, end) => [...Array(end - start + 1)]
   .map((_, index) => index + start)
   .filter(x => x % step === start % step);
0
danginkgo

Lösung:

//best performance
var range = function(start, stop, step) {
    var a = [start];
    while (start < stop) {
        start += step || 1;
        a.Push(start);
    }
    return a;
};

//or
var range = function(start, end) {
    return Array(++end-start).join(0).split(0).map(function(n, i) {
        return i+start
    });
}

Hier ist eine Definition einer Bereichsfunktion, die sich genau wie der range-Typ von Python verhält, mit der Ausnahme, dass diese nicht faul ist. Es sollte leicht sein, daraus einen Generator zu machen.

Die Argumente für den Bereichskonstruktor müssen Zahlen sein. Wenn das Schrittargument nicht angegeben wird, wird der Standardwert 1 verwendet. Wenn das Startargument nicht angegeben wird, wird der Standardwert 0 verwendet. Wenn Schritt null ist, wird ein Fehler ausgegeben.

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
DMfll

Ich möchte hinzufügen, was ich für eine sehr anpassbare Version halte, die sehr schnell ist. 

const range = (start, end) => {
    let all = [];
    if (typeof start === "string" && typeof end === "string") {
        // Return the range of characters using utf-8 least to greatest
        const s = start.charCodeAt(0);
        const e = end.charCodeAt(0);
        for (let i = s; i <= e; i++) {
            all.Push(String.fromCharCode(i));
        }
    } else if (typeof start === "number" && typeof end === "number") {
        // Return the range of numbers from least to greatest
        for(let i = end; i >= start; i--) {
            all.Push(i);
        }
    } else {
        throw new Error("Did not supply matching types number or string.");
    }
    return all;
}
// usage
const aTod = range("a", "d");

Auch TypeScript, wenn Sie möchten

const range = (start: string | number, end: string | number): string[] | number[] => {
    const all: string[] | number[] = [];
    if (typeof start === "string" && typeof end === "string") {
        const s: number = start.charCodeAt(0);
        const e: number = end.charCodeAt(0);
        for (let i = s; i <= e; i++) {
            all.Push(String.fromCharCode(i));
        }
    } else if (typeof start === "number" && typeof end === "number") {
        for (let i = end; i >= start; i--) {
            all.Push(i);
        }
    } else {
        throw new Error("Did not supply matching types number or string.");
    }
    return all;
}
// Usage
const negTenToten: number[] = range(-10, 10) as number[];

Mit etwas Einfluss von anderen Antworten gemacht. Benutzer ist jetzt weg.

0
mjwrazor

Wenn wir etwas wie [4, 2] eingeben, erhalten wir [2, 3, 4] als Ausgabe und können damit arbeiten.

function createRange(array) {
  var range = [];
  var highest = array.reduce(function(a, b) {
    return Math.max(a, b);
  });
  var lowest = array.reduce(function(a, b) {
    return Math.min(a, b);
  });
  for (var i = lowest; i <= highest; i++) {
    range.Push(i);
  }
  return range;
}
0

Hier ist ein einfacher Ansatz, der auf @benmcdonald und anderen basiert, jedoch mehr als eine Zeile.

let K = [];
for (i = 'A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++) {
  K.Push(String.fromCharCode(i))
};
console.log(K);

0
Mohamed Atia

Kodiert nach 2010 Spezifikationen (ya, es ist 2016 mit ES6 Generatoren). Hier ist mein Take mit Optionen, um die range()-Funktion des Pythons zu emulieren. 

Array.range = function(start, end, step){
    if (start == undefined) { return [] } // "undefined" check

    if ( (step === 0) )  {  return []; // vs. throw TypeError("Invalid 'step' input")
    }  // "step" == 0  check

    if (typeof start == 'number') { // number check
        if (typeof end == 'undefined') { // single argument input
            end = start;
            start = 0;
            step = 1;
        }
        if ((!step) || (typeof step != 'number')) {
          step = end < start ? -1 : 1;
        }

        var length = Math.max(Math.ceil((end - start) / step), 0);
        var out = Array(length);

        for (var idx = 0; idx < length; idx++, start += step) {
          out[idx] = start;
        }

        // Uncomment to check "end" in range() output, non Pythonic
        if ( (out[out.length-1] + step) == end ) { // "end" check
            out.Push(end)
        }

    } else { 
        // Historical: '&' is the 27th letter: http://nowiknow.com/and-the-27th-letter-of-the-alphabet/
        // Axiom: 'a' < 'z' and 'z' < 'A'
        // note: 'a' > 'A' == true ("small a > big A", try explaining it to a kid! )

        var st = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ&'; // axiom ordering

        if (typeof end == 'undefined') { // single argument input
            end = start;
            start = 'a';
        }

        var first = st.indexOf(start);
        var last = st.indexOf(end);

        if ((!step) || (typeof step != 'number')) {
          step = last < first ? -1 : 1;
        }

        if ((first == -1) || (last == -1 )) { // check 'first' & 'last'
            return []
        }

        var length = Math.max(Math.ceil((last - first) / step), 0);
        var out = Array(length);

        for (var idx = 0; idx < length; idx++, first += step) {
          out[idx] = st[first];
        } 

        // Uncomment to check "end" in range() output, non Pythonic
        if ( (st.indexOf(out[out.length-1]) + step ) == last ) { // "end" check
            out.Push(end)
        }
    }
    return out;
}

Beispiel:

Array.range(5);       // [0,1,2,3,4,5]
Array.range(4,-4,-2); // [4, 2, 0, -2, -4]
Array.range('a','d'); // ["a", "b", "c", "d"]
Array.range('B','y'); // ["B", "A", "z", "y"], different from chr() ordering
Array.range('f');     // ["a", "b", "c", "d", "e", "f"]
Array.range(-5);      // [], similar to python
Array.range(-5,0)     // [-5,-4-,-3-,-2,-1,0]
0
Alvin K.

Mein Take verwendet bedingte ternäre Operatoren in der for-Schleife (allerdings kein Argumentieren).

function range(start,end,step){
   var resar = [];
   for (var i=start;(step<0 ? i>=end:i<=end); i += (step == undefined ? 1:step)){
       resar.Push(i);
     };
   return resar;
};
0
dorvak

Bei Briefen handelt es sich um eine einfache Lösung von Vanilla JS, mit der ich Briefmarken generieren wollte. Es soll nur Arrays aus Groß- oder Kleinbuchstaben erzeugen.

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"));

0
Madbreaks