Erstellen Sie ein Array mit demselben Element, das mehrmals wiederholt wird

322

In Python, wo [2]sich eine Liste befindet, gibt der folgende Code diese Ausgabe aus:

[2] * 5 # Outputs: [2,2,2,2,2]

Gibt es eine einfache Möglichkeit, dies mit einem Array in JavaScript zu tun?

Ich habe die folgende Funktion geschrieben, aber gibt es etwas kürzeres oder besseres?

var repeatelem = function(elem, n){
    // returns an array with element elem repeated n times.
    var arr = [];

    for (var i = 0; i <= n; i++) {
        arr = arr.concat(elem);
    };

    return arr;
};
Curious2learn
quelle
4
Mögliches Duplikat: stackoverflow.com/questions/1295584/…
Larry Battle

Antworten:

52

Sie können es so machen:

function fillArray(value, len) {
  if (len == 0) return [];
  var a = [value];
  while (a.length * 2 <= len) a = a.concat(a);
  if (a.length < len) a = a.concat(a.slice(0, len - a.length));
  return a;
}

Das Array wird in jeder Iteration verdoppelt, sodass mit wenigen Iterationen ein wirklich großes Array erstellt werden kann.


Hinweis: Sie können Ihre Funktion auch erheblich verbessern, indem Sie pushanstelle von verwenden concat, da concatbei jeder Iteration ein neues Array erstellt wird. So (nur als Beispiel dafür gezeigt, wie Sie mit Arrays arbeiten können):

function fillArray(value, len) {
  var arr = [];
  for (var i = 0; i < len; i++) {
    arr.push(value);
  }
  return arr;
}
Guffa
quelle
11
Es ist viel effizienter, alle Einträge im Voraus arr = new Array(len);zuzuweisen und sie dann durch Index in der Schleife zuzuweisen, d arr[i] = value;. H. Auf diese Weise zahlen Sie nur O (n), anstatt das Array während des Wachstums neu zuweisen zu müssen. Im Allgemeinen ist es immer besser, wachsende Arrays durch Anhängen zu vermeiden, wenn dies möglich ist. Wenn Sie die endgültige Größe kennen, verwenden Sie sie.
Tom Karzes
25
Array.from({length:5}).map(x => 2)
Noobninja
1
@noobninja: tolle Lösung; Sie sollten es als Antwort erneut eingeben, damit es positiv bewertet werden kann.
Jsalvata
691

In ES6 mithilfe der Array fill () -Methode

Array(5).fill(2)
//=> [2, 2, 2, 2, 2]
Niko Ruotsalainen
quelle
3
Internet Explorer und Opera unterstützen dies noch nicht.
DenisKolodin
4
Node.js <= 3 unterstützt dies nicht.
Junle Li
1
@DenisKolodin Current Opera tut. Und Edge auch. Siehe kompatible Tabelle
Janus Troelsen
4
@ Michael Du kannst es mit machen Array(5).fill([1,2,3]).flat(). Beachten Sie, dass flat () immer noch sehr experimentell ist und die Browserunterstützung schlecht ist.
Niko Ruotsalainen
3
Beachten Sie, dass das Argument to filleinmal ausgewertet wird, sodass Array(9).fill(someMutable)neun Verweise auf someMutabledas Array erstellt werden (durch Mutation eines wird 'all' mutiert).
Carl Smith
146
>>> Array.apply(null, Array(10)).map(function(){return 5})
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
>>> //Or in ES6
>>> [...Array(10)].map((_, i) => 5)
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
Janus Troelsen
quelle
6
Dumme Frage, aber warum funktioniert die neue Array (10) .map nicht?
Blazkovicz
1
blazkovicz, siehe zertoshs Kommentar zu dieser Antwort aus dem Grund.
Ross Rogers
5
Mit ES6 kann dies Array(...Array(10)).map(() => 5)mit dem Spread-Operator oder auch mitArray.from(Array(10)).map(() => 5)
Christophe Vidal
4
Laut MDN können Sie einfach so:Array.from({length: 10}, () => 5);
Plusb Preco
2
@blazkovicz Array (10) erstellt ein Array lenght = 10ohne aufzählbare Eigenschaften. .mapfunktioniert nur bei aufzählbaren Eigenschaften. Die .applyMethode nimmt dieses Array und ordnet es einem arguments array(Array-ähnlichen Objekt) zu, das an die ArrayKonstruktorfunktion übergeben werden soll. Das Argumentarray kann nicht dünn sein, daher werden die fehlenden Eigenschaften auf gesetzt undefinedund aufzählbar. Jetzt können wir .mapwie vorgesehen verwenden
CervEd
91

Du kannst es versuchen:

Array(6).join('a').split(''); // returns ['a','a','a','a','a'] (5 times)

Update (01/06/2018) :

Jetzt können Sie eine Reihe von Zeichen wiederholen lassen.

new Array(5).fill('a'); // give the same result as above;
// or
Array.from({ length: 5 }).fill('a')

Hinweis: Weitere Informationen zu Kompatibilität (...) und von (...) finden Sie auf Kompatibilität und Browserunterstützung.

Update (11.05.2019) :

Eine andere Möglichkeit, ohne filloder zu verwenden from, funktioniert für Zeichenfolgen beliebiger Länge:

Array.apply(null, Array(3)).map(_ => 'abc') // ['abc', 'abc', 'abc']

Gleich wie oben Antwort . Der Vollständigkeit halber hinzufügen.

Vivek
quelle
1
Nett. Am kürzesten und einfacher.
Johann Echavarria
2
+1 für einfache Handhabung. Schade, dass Sie daraus kein Array leerer Strings erstellen können. Abgesehen davon sehr klug ...
Schneller
1
Array (6) .join ('a'). Split ('a') gibt mir ein Array mit leeren Zeichenfolgen.
Vivek
17
Dies funktioniert nur für 1 Zeichenfolgen, sodass die Frage nicht vollständig beantwortet wird.
Az_
3
@AlfonsoVergara: In Javascript ist String ein primitiver (wertsemantischer) Typ. Es gibt keine Möglichkeit, zwei Zeichenfolgen dazu zu bringen, auf dieselben Daten zu verweisen (da Zeichenfolgen in Javascript keine Verweise sind; sie sind Werte). Sie müssen auf Referenzsemantik mit Objekten und Listen achten, aber nicht mit Zeichenfolgen.
Quuxplusone
36

Array.from({length:5}, i => 1) // [1, 1, 1, 1, 1]

oder erstellen Sie ein Array mit zunehmendem Wert

Array.from({length:5}, (e, i)=>i) // [0, 1, 2, 3, 4]

Thomson
quelle
Schön, 👍 dies ist der beste Ansatz, wenn Sie das Element für die Dynamik benötigen
IliasT
Array.from({length:5}, i => 1)=> iist, undefinedda es einen leeren Wert darstellt Array.from({length:5}, (e, i)=>i)=> eist, undefinedweil es einen leeren Wert darstellt. Es sollte sein Array.from({length:5}, v => 1)undArray.from({length:5}, (v, i)=>i)
Rafal endet am
33

In lodash ist es nicht so schlimm:

_.flatten(_.times(5, function () { return [2]; }));
// [2, 2, 2, 2, 2]

EDIT : Noch besser:

_.times(5, _.constant(2));
// [2, 2, 2, 2, 2]

EDIT : Noch besser:

_.fill(Array(5), 2);
Droogans
quelle
3
_.times (Länge, _.constant (Wert))
user1533401
1
aus den Dokumenten: _.fill (Array (3), 2); Welches ist nicht weit von ES6
kert
15

[c] * n kann geschrieben werden als:

Array(n+1).join(1).split('').map(function(){return c;})

so für [2] * 5

Array(6).join(1).split('').map(function(){return 2;})
Bach Hong
quelle
Wäre Array (6) .join (2) .split ('') nicht einfacher? Warum brauchst du die Karte?
Angela
4
das gibt ["2", "2", "2", "2", "2"] anstelle von [2, 2, 2, 2, 2] zurück.
Brook Hong
10

Sie können die Funktionalität von Array auch folgendermaßen erweitern:

Array.prototype.fill = function(val){
    for (var i = 0; i < this.length; i++){
        this[i] = val;
    }
    return this;
};
// used like:
var arry = new Array(5)​.fill(2);
// or
var arry = new Array(5);
arry.fill(2);


console.log(arry);​ //[2, 2, 2, 2, 2] 

Ich sollte beachten, dass das Erweitern der Funktionalität von integrierten Objekten Probleme verursachen kann, wenn Sie mit Bibliotheken von Drittanbietern arbeiten. Wägen Sie dies immer in Ihre Entscheidungen ein.

Shmiddty
quelle
Beachten Sie, dass, wenn Sie ein Objekt an filljeden Index im Array übergeben, sich auf dasselbe Objekt bezieht. Wenn Sie also eines ändern, werden alle geändert. Dies ist nicht allzu schwer zu lösen, wenn es zu einem Problem wird.
Shmiddty
Ich verstehe nicht, warum viele Javascript-Benutzer nicht wissen, dass native Funktionen nicht prototypisiert werden müssen.
BrooNo
2
A Fill - Methode wurde in ES6 hinzugefügt. Ich würde also nicht empfehlen, dem Prototyp eigene Inhalte hinzuzufügen. Sie werden die schnellere und leistungsfähigere Version überschreiben.
Janus Troelsen
1
@JanusTroelsen Um zu vermeiden, dass Javascript oder Bibliotheken von Drittanbietern überschrieben werden, können Sie vor dem Deklarieren überprüfen, ob sie vorhanden sind. if (!Array.prototype.fill) { }
Oliver
1
@JanusTroelsen Was meinst du mit "echte Polyfüllung"?. Ich habe ein polifyll verwendet. Ich meine: Überprüfen Sie, ob Funktionen erkannt und implementiert wurden, falls dies nicht der Fall ist.
Oliver
5

Falls Sie ein Array mehrmals wiederholen müssen :

var arrayA = ['a','b','c'];
var repeats = 3;
var arrayB = Array.apply(null, {length: repeats * arrayA.length})
        .map(function(e,i){return arrayA[i % arrayA.length]});
// result: arrayB = ['a','b','c','a','b','c','a','b','c']

inspiriert von dieser Antwort

Henrik Christensen
quelle
in es6 können Sie "abc" .repeat (3)
Janus Troelsen
4

Kein einfacher Weg. Sie müssen eine Schleife erstellen und Elemente in das Array verschieben.

Diodeus - James MacFarlane
quelle
Vielen Dank! Bevor ich akzeptiere, ist pushes concatin Bezug auf die Effizienz besser oder besser?
Curious2learn
CONCAT muss zwei Arrays untersuchen, PUSH fügt nur ein weiteres Element hinzu, daher würde ich erwarten, dass PUSH im Allgemeinen effizienter ist, aber für die IDENTISCHEN DATEN denke ich, dass Guffas Antwort es nagelt.
Diodeus - James MacFarlane
Keine Notwendigkeit für Schleifen, siehe meine Antwort.
Janus Troelsen
@ JanusTroelsen, keine Schleife erforderlich, es sei denn, Sie möchten eine effiziente Möglichkeit, diese Aktion auszuführen. Ihre ist eine der langsameren Impementation, die Sie finden können. push () to [] ist am schnellsten.
Chrilith
4

Verwenden Sie diese Funktion:

function repeatElement(element, count) {
    return Array(count).fill(element)
}
>>> repeatElement('#', 5).join('')
"#####"

Oder für eine kompaktere Version:

const repeatElement = (element, count) =>
    Array(count).fill(element)
>>> repeatElement('#', 5).join('')
"#####"

Oder für eine Curry-fähige Version:

const repeatElement = element => count =>
    Array(count).fill(element)
>>> repeatElement('#')(5).join('')
"#####"

Sie können diese Funktion mit einer Liste verwenden:

const repeatElement = (element, count) =>
    Array(count).fill(element)

>>> ['a', 'b', ...repeatElement('c', 5)]
['a', 'b', 'c', 'c', 'c', 'c', 'c']
Ken Mueller
quelle
4

Wenn Sie ein Array wiederholen müssen, verwenden Sie Folgendes.

Array.from({ length: 3 }).fill(['a','b','c']).flat()

wird zurückkehren

Array(9) [ "a", "b", "c", "a", "b", "c", "a", "b", "c" ]
Etoxin
quelle
Toller Oneliner mit einem vorhandenen Array, was ich brauchte.
Gneric
2

Ein weiterer Einzeiler:

Array.prototype.map.call([]+Array(5+1),function(){ return '2'; })
Filip Hermans
quelle
1

Diese Funktion erstellt ein Array von (Längen-) Elementen, wobei jedes Element gleich (Wert) ist, solange (Wert) eine Ganzzahl oder eine Zeichenfolge einer Ganzzahl ist. Alle Dezimalzahlen werden abgeschnitten. Wenn Sie Dezimalzahlen möchten, ersetzen Sie "parseInt ( " durch " parseFloat ( ").

function fillArray(length, intValue) {
     var vals = (new Array(length + 1)).join(intValue + '|').split('|').slice(0,length);
     for(var i = 0; i < length; i += 1) {
         vals[i] = parseInt(vals[i]);
     }
     return vals;
}

Beispiele:

fillArray(5, 7) // returns [7,7,7,7,7]
fillArray(5, 7.5) // returns [7,7,7,7,7]
fillArray(5, 200) // returns [200,200,200,200,200]
TxRegex
quelle
1

Ich hatte Probleme mit den genannten Methoden, wenn ich ein Array wie

var array = ['foo', 'bar', 'foobar'];
var filled = array.fill(7);

//filled should be ['foo', 'bar', 'foobar', 'foo', 'bar', 'foobar', 'foo']

Um dies zu bekommen, benutze ich:

Array.prototype.fill = function(val){
    var l = this.length;
    if(l < val){
        for(var i = val-1-l; i >= 0; i--){
            this[i+l] = this[i % l];
        }
    }
    return this;
};
Xaver
quelle
Das ist schön, sollte aber wohl benannt werden cycle.
Drenmi
1

Ich habe dies heute entdeckt, als ich versucht habe, ein 2D-Array ohne Schleifen zu erstellen. Rückblickend ist das Verbinden eines neuen Arrays ordentlich. Ich habe versucht, ein neues Array zuzuordnen, was nicht funktioniert, da die Zuordnung leere Slots überspringt.

"#".repeat(5).split('').map(x => 0)

Das Zeichen "#" kann ein beliebiges gültiges Einzelzeichen sein. Die 5 wäre eine Variable für die Anzahl der gewünschten Elemente. Die 7 wäre der Wert, mit dem Sie Ihr Array füllen möchten.

Die neue Füllmethode ist besser, und als ich sie codierte, wusste ich nicht, dass sie existiert, und ich wusste auch nicht, dass Wiederholung es6 ist. Ich werde einen Blog-Beitrag über die Verwendung dieses Tricks in Verbindung mit Reduzieren schreiben, um coole Dinge zu tun.

http://jburger.us.to/2016/07/14/functionally-create-a-2d-array/

Magischer Gordon
quelle
1

Versuche dies:

"avinash ".repeat(5).trim().split(" ");
Avinash
quelle
1

var finalAry = [..."2".repeat(5).split("")].map(Number);
console.log(finalAry);

Amaldev ps
quelle
0

Wenn Sie einen Utlity-Gürtel wie lodash / underscore verwenden, können Sie dies so tun :)

let result = _.map(_.times(foo), function() {return bar})
Shane Rogers
quelle
0

Kann auch als Einzeiler verwendet werden:

function repeat(arr, len) {
    while (arr.length < len) arr = arr.concat(arr.slice(0, len-arr.length));
    return arr;
}
Sarsaparille
quelle
0

Dies verbessert die Antwort von Vivek und funktioniert für Zeichenfolgen beliebiger Länge, um ein Array mit der Länge n zu füllen:Array(n+1).join('[string to be repeated][separator]').split('[separator]').slice(0, n)

Tigregalis
quelle
-1

Ich brauchte eine Möglichkeit, ein Array (mit n Elementen) m-mal zu wiederholen / zu schleifen.

Verteilen Sie beispielsweise eine Liste (von Personen) auf eine Woche / einen Monat. Nehmen wir an, ich habe drei Namen und möchte, dass sie sich in einer Woche wiederholen:

fillArray(["Adam", "Blair", "Curtis"], 7); // returns ["Adam", "Blair", "Curtis", "Adam", "Blair", "Curtis", "Adam"]

function fillArray(pattern, count) {
    let result = [];
    if (["number", "string"].includes(typeof pattern)) {
        result = new Array(5);
        result.fill(pattern);
    }
    else if (pattern instanceof Array) {
        for (let i = 0; i < count; i++) {
            result = result.concat(pattern);
        }
        result = result.slice(0, count);
    }
    return result;
}

fillArray("a", 5);        // ["a", "a", "a", "a", "a"]
fillArray(1, 5);          // [1, 1, 1, 1, 1]
fillArray(["a", "b"], 5); // ["a", "b", "a", "b", "a"]
Akinuri
quelle