Créer un tableau avec le même élément répété plusieurs fois


323

En Python, où se [2]trouve une liste, le code suivant donne cette sortie:

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

Existe-t-il un moyen simple de le faire avec un tableau en JavaScript?

J'ai écrit la fonction suivante pour le faire, mais y a-t-il quelque chose de plus court ou de meilleur?

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


Réponses:


52

Vous pouvez le faire comme ceci:

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

Il double le tableau à chaque itération, de sorte qu'il peut créer un tableau vraiment grand avec peu d'itérations.


Remarque: Vous pouvez également améliorer considérablement votre fonction en utilisant pushau lieu de concat, comme concatcela créera un nouveau tableau à chaque itération. Comme ceci (montré juste comme un exemple de la façon dont vous pouvez travailler avec des tableaux):

function fillArray(value, len) {
  var arr = [];
  for (var i = 0; i < len; i++) {
    arr.push(value);
  }
  return arr;
}

11
Il est beaucoup plus efficace d'allouer toutes les entrées en amont, avec arr = new Array(len);, puis de les affecter par index dans la boucle, c'est-à-dire arr[i] = value;. De cette façon, vous ne payez que O (n) plutôt que de devoir réallouer le tableau à mesure qu'il grandit. En général, il est toujours préférable d'éviter de développer des tableaux en les ajoutant si possible. Si vous connaissez la taille finale, utilisez-la.
Tom Karzes

26
Array.from({length:5}).map(x => 2)
noobninja

1
@noobninja: excellente solution; vous devez le saisir à nouveau comme réponse afin qu'il puisse être voté.
jsalvata

693

En utilisant ES6 Matrice de remplissage () Méthode

Array(5).fill(2)
//=> [2, 2, 2, 2, 2]

3
Internet Explorer et Opera ne le prennent pas encore en charge.
DenisKolodin

4
Node.js <= 3 ne prend pas en charge cela.
Junle Li

1
@DenisKolodin Current Opera le fait. Et Edge aussi. Voir compat-table
Janus Troelsen

4
@Michael Vous pouvez le faire avec Array(5).fill([1,2,3]).flat(). Notez que flat () est toujours très expérimental et le support du navigateur est médiocre.
Niko Ruotsalainen

3
Notez que l'argument to fillest évalué une fois, donc Array(9).fill(someMutable)crée neuf références à someMutabledans le tableau (une mutation mutant «toutes»).
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]

6
Question idiote, mais pourquoi le nouveau Array (10) .map ne fonctionne pas?
blazkovicz

1
blazkovicz, voir le commentaire de zertosh sur cette réponse pour la raison.
Ross Rogers

5
Avec ES6, cela peut être «mis à niveau» vers Array(...Array(10)).map(() => 5)avec l'opérateur de propagation ou aussi versArray.from(Array(10)).map(() => 5)
Christophe Vidal

4
Selon MDN , vous pouvez simplement aimer ceci:Array.from({length: 10}, () => 5);
Plusb Preco

2
@blazkovicz Array (10) crée un tableau lenght = 10sans propriétés énumérables. .mapne fonctionne que sur les propriétés énumérables. La .applyméthode prend ce tableau et le mappe dans un arguments array(un objet de type tableau) à transmettre à la Arrayfonction constructeur. Le tableau d'arguments ne peut pas être clairsemé, donc les propriétés manquantes sont définies sur undefinedet deviennent énumérables. Maintenant, nous pouvons utiliser .mapcomme prévu
CervEd

91

tu peux essayer:

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

Mise à jour (01/06/2018) :

Vous pouvez maintenant répéter un ensemble de caractères.

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

Remarque: Vérifiez plus sur fill (...) et from (...) pour la compatibilité et la prise en charge du navigateur.

Mise à jour (05/11/2019) :

Une autre façon, sans utiliser fillou from, qui fonctionne pour une chaîne de n'importe quelle longueur:

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

Identique à la réponse ci-dessus . Ajout par souci d'exhaustivité.


1
Agréable. Le plus court et le plus simple.
Johann Echavarria

2
+1 pour une manipulation simple. Dommage que vous ne puissiez pas créer un tableau de chaînes vides à partir de cela. A part ça, c'est très intelligent ...
Plus rapide

1
Array (6) .join ('a'). Split ('a') me donne un tableau de chaîne vide.
Vivek

17
Cela ne fonctionne que pour 1 chaîne de caractères, donc cela ne répond pas complètement à la question.
az_

3
@AlfonsoVergara: En Javascript, String est un type primitif (sémantique de valeur); il n'y a aucun moyen d'obtenir deux chaînes pour référencer les mêmes données (car les chaînes ne sont pas des références en Javascript; ce sont des valeurs). Vous devez faire attention à la sémantique de référence avec les objets et les listes, mais pas avec les chaînes.
Quuxplusone

36

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

ou créer un tableau avec une valeur croissante

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


Bien, c'est la meilleure approche si vous avez besoin de l'élément pour
dynamiser

Array.from({length:5}, i => 1)=> iest est undefinedcar il représente une valeur vide Array.from({length:5}, (e, i)=>i)=> eest undefinedcar il représente une valeur vide. Ça devrait être Array.from({length:5}, v => 1)etArray.from({length:5}, (v, i)=>i)
Rafal Enden

33

En lodash ce n'est pas si mal:

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

EDIT : Encore mieux:

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

EDIT : Encore mieux:

_.fill(Array(5), 2);

3
_.times (longueur, _.constant (valeur))
user1533401

1
à partir des documents: _.fill (Array (3), 2); Qui n'est pas loin de l'ES6
kert

15

[c] * n peut s'écrire:

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

donc pour [2] * 5

Array(6).join(1).split('').map(function(){return 2;})

En fait, Array (6) .join (2) .split ('') ne serait-il pas plus facile? Pourquoi auriez-vous besoin de la carte?
Angela

4
qui renvoie ["2", "2", "2", "2", "2"], au lieu de [2, 2, 2, 2, 2].
brook hong

10

Vous pouvez également étendre les fonctionnalités d'Array comme suit:

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] 

Je dois noter que l'extension des fonctionnalités des objets intégrés peut provoquer des problèmes si vous travaillez avec des bibliothèques tierces. Considérez toujours cela dans vos décisions.


Notez que si vous passez un objet dans fillchaque index du tableau fera référence au même objet, donc en changer un les changera tous. Ce n'est pas trop difficile à résoudre si cela devient un problème.
Shmiddty du

Je ne comprends pas pourquoi de nombreux utilisateurs de javascript ignorent la nécessité de ne pas prototyper les fonctions natives.
brooNo

2
Une méthode de remplissage a été ajoutée dans ES6. Je ne recommanderais donc pas d'ajouter vos propres trucs au prototype, vous allez écraser la version plus rapide et plus performante.
Janus Troelsen

1
@JanusTroelsen Pour éviter d'écraser des bibliothèques javascript ou tierces, vous pouvez vérifier s'il existe avant de le déclarer. if (!Array.prototype.fill) { }
Oliver

1
@JanusTroelsen Qu'entendez-vous par "vrai polyfill"?. J'ai utilisé un polifyll. Je veux dire: vérifiez la détection et la mise en œuvre des fonctionnalités dans le cas contraire.
Oliver


5

Si vous devez répéter plusieurs fois un tableau :

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

inspiré par cette réponse


dans es6, vous pouvez faire "abc" .repeat (3)
Janus Troelsen

4

Pas de moyen plus simple. Vous devez créer une boucle et pousser des éléments dans le tableau.


Merci! Avant d'accepter, c'est pushmieux ou concatmieux, en termes d'efficacité?
Curious2learn

CONCAT doit inspecter deux tableaux, PUSH ajoute juste un autre élément, donc je m'attendrais à ce que PUSH soit plus efficace en général, mais pour les DONNÉES IDENTIQUES je pense que la réponse de Guffa le résume.
Diodeus - James MacFarlane

Pas besoin de boucles, voir ma réponse.
Janus Troelsen

@JanusTroelsen, pas besoin de boucler sauf si vous voulez un moyen efficace de faire cette action. La vôtre est l'une des plus lentes à mettre en œuvre. push () to [] est le plus rapide.
chrilith

4

Utilisez cette fonction:

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

Ou pour une version plus compacte:

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

Ou pour une version curry:

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

Vous pouvez utiliser cette fonction avec une liste:

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

>>> ['a', 'b', ...repeatElement('c', 5)]
['a', 'b', 'c', 'c', 'c', 'c', 'c']

4

Si vous devez répéter un tableau, utilisez ce qui suit.

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

reviendra

Array(9) [ "a", "b", "c", "a", "b", "c", "a", "b", "c" ]

grand oneliner utilisant un tableau existant, ce dont j'avais besoin.
gneric

2

Un autre doublure:

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

1

Cette fonction crée un tableau d'éléments (longueur) où chaque élément est égal à (valeur) tant que (valeur) est un entier ou une chaîne d'un entier. Tous les nombres décimaux seront tronqués. Si vous voulez des nombres décimaux, remplacez "parseInt ( " par " 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;
}

Exemples:

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]

1

J'ai eu des problèmes avec les méthodes mentionnées lorsque j'utilise un tableau comme

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

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

Pour l'obtenir, j'utilise:

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

C'est bien, mais devrait probablement être nommé cycle.
Drenmi

1

J'ai découvert cela aujourd'hui en essayant de créer un tableau 2D sans utiliser de boucles. Rétrospectivement, rejoindre un nouveau tableau est bien; J'ai essayé de mapper un nouveau tableau, ce qui ne fonctionne pas car la carte saute les emplacements vides.

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

Le caractère "#" peut être n'importe quel caractère unique valide. Le 5 serait une variable pour le nombre d'éléments que vous souhaitez. Le 7 serait la valeur avec laquelle vous souhaitez remplir votre tableau.

La nouvelle méthode de remplissage est meilleure, et lorsque j'ai codé cela, je ne savais pas qu'elle existait et je ne savais pas que répéter était es6; Je vais écrire un article de blog sur l'utilisation de cette astuce en tandem avec réduire pour faire des choses sympas.

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




0

Si vous utilisez une ceinture utlity comme lodash / underscore, vous pouvez le faire comme ceci :)

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

0

Peut également être utilisé comme doublure:

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

0

Améliorant la réponse de Vivek , cela fonctionne pour des chaînes de n'importe quelle longueur, pour remplir un tableau de longueur n:Array(n+1).join('[string to be repeated][separator]').split('[separator]').slice(0, n)


-1

J'avais besoin d'un moyen de répéter / boucler un tableau (avec n éléments) m fois.

Par exemple, distribuer une liste (de personnes) à une semaine / mois. Disons que j'ai 3 noms, et je veux qu'ils répètent dans une semaine:

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"]
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.