Il ne semble pas y avoir de moyen d'étendre un tableau JavaScript existant avec un autre tableau, c'est-à-dire d'émuler la extend
méthode de Python .
Je veux atteindre les objectifs suivants:
>>> a = [1, 2]
[1, 2]
>>> b = [3, 4, 5]
[3, 4, 5]
>>> SOMETHING HERE
>>> a
[1, 2, 3, 4, 5]
Je sais qu'il existe une a.concat(b)
méthode, mais elle crée un nouveau tableau au lieu d'étendre simplement le premier. Je voudrais un algorithme qui fonctionne efficacement lorsqu'il a
est beaucoup plus grand que b
(c'est-à-dire qui ne copie pas a
)
Remarque: Ce n'est pas un doublon de Comment ajouter quelque chose à un tableau? - le but ici est d'ajouter tout le contenu d'un tableau à l'autre, et de le faire "sur place", c'est-à-dire sans copier tous les éléments du tableau étendu.
a.push(...b)
. Son concept est similaire à la réponse du haut, mais mis à jour pour ES6.Réponses:
La
.push
méthode peut prendre plusieurs arguments. Vous pouvez utiliser l' opérateur d'étalement pour passer tous les éléments du deuxième tableau comme arguments pour.push
:Si votre navigateur ne prend pas en charge ECMAScript 6, vous pouvez utiliser à la
.apply
place:Ou peut-être, si vous pensez que c'est plus clair:
Veuillez noter que toutes ces solutions échoueront avec une erreur de débordement de pile si le tableau
b
est trop long (le problème commence à environ 100 000 éléments, selon le navigateur).Si vous ne pouvez pas garantir que
b
c'est assez court, vous devez utiliser une technique standard basée sur la boucle décrite dans l'autre réponse.la source
push
méthode de Array peut prendre n'importe quel nombre d'arguments, qui sont ensuite poussés à l'arrière du tableau. Il ena.push('x', 'y', 'z')
va de même pour un appel valide qui s'étendraa
sur 3 éléments.apply
est une méthode de n'importe quelle fonction qui prend un tableau et utilise ses éléments comme s'ils étaient tous donnés explicitement comme éléments positionnels à la fonction. Ila.push.apply(a, ['x', 'y', 'z'])
faudrait donc également étendre le tableau de 3 éléments. De plus,apply
prend un contexte comme premier argument (nous y passons àa
nouveau pour l'ajoutera
).[].push.apply(a, b)
.Mise à jour 2018 : Une meilleure réponse est une plus récente de la mine :
a.push(...b)
. Ne votez plus pour celui-ci, car il n'a jamais vraiment répondu à la question, mais c'était un hack de 2015 autour du premier hit sur Google :)Pour ceux qui ont simplement recherché "JavaScript array extend" et sont arrivés ici, vous pouvez très bien les utiliser
Array.concat
.Concat retournera une copie du nouveau tableau, comme le démarreur de thread ne le voulait pas. Mais vous pourriez ne pas vous en soucier (certainement pour la plupart des types d'utilisations, ce sera parfait).
Il y a aussi du bon sucre ECMAScript 6 pour cela sous la forme de l'opérateur de propagation:
(Il copie également.)
la source
arr.push(...arr2)
soit plus récent et meilleur et une réponse techniquement correcte (tm) à cette question particulière.Vous devez utiliser une technique basée sur une boucle. Les autres réponses de cette page basées sur l'utilisation
.apply
peuvent échouer pour les grands tableaux.Une implémentation en boucle assez concise est:
Vous pouvez ensuite effectuer les opérations suivantes:
La réponse de DzinX (en utilisant push.apply) et d'autres
.apply
méthodes basées échouent lorsque le tableau que nous ajoutons est grand (les tests montrent que pour moi, grand est> 150 000 entrées environ dans Chrome et> 500 000 entrées dans Firefox). Vous pouvez voir cette erreur se produire dans ce jsperf .Une erreur se produit car la taille de la pile d'appels est dépassée lorsque «Function.prototype.apply» est appelé avec un grand tableau comme deuxième argument. (MDN a une note sur les dangers de dépasser la taille de la pile d'appels en utilisant Function.prototype.apply - voir la section intitulée "Appliquer et fonctions intégrées".)
Pour une comparaison de vitesse avec d'autres réponses sur cette page, consultez ce jsperf (grâce à EaterOfCode). L'implémentation basée sur la boucle est similaire en vitesse à l'utilisation
Array.push.apply
, mais a tendance à être un peu plus lente queArray.slice.apply
.Fait intéressant, si le tableau que vous ajoutez est clairsemé, la
forEach
méthode basée ci-dessus peut tirer parti de la rareté et surpasser les.apply
méthodes basées; consultez ce jsperf si vous voulez le tester par vous-même.Soit dit en passant, ne soyez pas tenté (comme je l'étais!) De raccourcir encore la mise en œuvre de forEach pour:
car cela produit des résultats poubelles! Pourquoi? Parce que
Array.prototype.forEach
fournit trois arguments à la fonction qu'elle appelle - ce sont: (element_value, element_index, source_array). Tous ces éléments seront poussés sur votre premier tableau à chaque itération deforEach
si vous utilisez "forEach (this.push, this)"!la source
.push.apply
est en fait beaucoup plus rapide qu'en.forEach
v8, le plus rapide est toujours une boucle en ligne..forEach
est plus rapide que.push.apply
dans Chrome / Chromium (dans toutes les versions depuis la v25). Je n'ai pas pu tester la v8 isolément, mais si vous l'avez, veuillez lier vos résultats. Voir jsperf: jsperf.com/array-extending-push-vs-concat/5undefined
,.forEach
sautez-les, ce qui en fait le plus rapide..splice
est en fait le plus rapide?! jsperf.com/array-extending-push-vs-concat/18Je pense que le plus élégant de nos jours est:
L' article de MDN sur l'opérateur de spread mentionne cette belle manière sucrée dans ES2015 (ES6):
Notez que
arr2
cela ne peut pas être énorme (gardez-le sous environ 100 000 éléments), car la pile d'appels déborde, selon la réponse de jcdude.la source
arr1.push(arr2)
. Cela peut être un problème commearr1 = []; arr2=['a', 'b', 'd']; arr1.push(arr2)
le résultat étant un tableau de tableauxarr1 == [['a','b','d']]
plutôt que deux tableaux combinés. C'est une erreur facile à faire. Je préfère votre deuxième réponse ci-dessous pour cette raison. stackoverflow.com/a/31521404/4808079.concat
c'est que le deuxième argument ne doit pas être un tableau. Ceci peut être réalisé en combinant l'opérateur de propagation avecconcat
, par exemplearr1.push(...[].concat(arrayOrSingleItem))
D'abord quelques mots sur
apply()
JavaScript pour comprendre pourquoi nous l'utilisons:Push attend une liste d'éléments à ajouter au tableau. Le
apply()
procédé, cependant, prend les arguments attendus pour l'appel de fonction sous forme de tableau. Cela nous permet de facilementpush
les éléments d'un tableau dans un autre tableau avec lapush()
méthode intégrée .Imaginez que vous ayez ces tableaux:
et faites simplement ceci:
Le résultat sera:
La même chose peut être effectuée dans ES6 en utilisant l'opérateur d'étalement ("
...
") comme ceci:Plus court et meilleur mais pas entièrement pris en charge dans tous les navigateurs pour le moment.
De plus, si vous souhaitez tout déplacer du tableau
b
vers lea
vidageb
dans le processus, vous pouvez le faire:et le résultat sera le suivant:
la source
while (b.length) { a.push(b.shift()); }
non?Si vous souhaitez utiliser jQuery, il y a $ .merge ()
Exemple:
Résultat: a =
[1, 2, 3, 4, 5]
la source
jQuery.merge()
?J'aime la
a.push.apply(a, b)
méthode décrite ci-dessus, et si vous le souhaitez, vous pouvez toujours créer une fonction de bibliothèque comme celle-ci:et l'utiliser comme ça
la source
Il est possible de le faire en utilisant
splice()
:Mais bien qu'il soit plus laid, il n'est pas plus rapide que
push.apply
, du moins pas dans Firefox 3.0.la source
Cette solution fonctionne pour moi (en utilisant l'opérateur de propagation d'ECMAScript 6):
la source
Vous pouvez créer un polyfill pour étendre comme je l'ai ci-dessous. Cela ajoutera au tableau; en place et se retourner, de sorte que vous pouvez enchaîner d'autres méthodes.
la source
Combiner les réponses ...
la source
Une autre solution pour fusionner plus de deux baies
Ensuite, appelez et imprimez comme:
La sortie sera:
Array [1, 2, 3, 4, 5, 6, 7]
la source
La réponse est super simple.
Concat agit de manière très similaire à la concaténation de chaînes JavaScript. Il renverra une combinaison du paramètre que vous mettez dans la fonction concat à la fin du tableau sur lequel vous appelez la fonction. Le nœud est que vous devez affecter la valeur retournée à une variable ou elle se perd. Donc par exemple
la source
Array.prototype.concat()
MDN, cela retournera un nouveau tableau , il ne s'ajoutera pas au tableau existant comme OP le demandait clairement.Utiliser
Array.extend
au lieu deArray.push
pour> 150 000 enregistrements.la source
Super simple, ne compte pas sur les opérateurs de spread ou ne s'applique pas, si c'est un problème.
Après avoir exécuté des tests de performances à ce sujet, c'est terriblement lent, mais répond à la question concernant la non-création d'un nouveau tableau. Concat est beaucoup plus rapide, même celui de jQuery
$.merge()
.https://jsperf.com/merge-arrays19b/1
la source
.forEach
plutôt que.map
si vous n'utilisez pas la valeur de retour. Il transmet mieux l'intention de votre code..map
mais vous pourriez aussi le faireb.forEach(function(x) { a.push(x)} )
. En fait, j'ai ajouté cela au test jsperf et c'est un cheveu plus rapide que la carte. Toujours super lent..map
ici a l'air très bizarre. Ce serait comme appelerb.filter(x => a.push(x))
. Cela fonctionne, mais cela déroute le lecteur en laissant entendre que quelque chose se passe alors que ce n'est pas le cas..map()
ça fait et c'est ça le problème. Cette connaissance me ferait penser que vous avez besoin du tableau résultant, sinon ce serait une bonne chose à utiliser.forEach()
pour rendre le lecteur prudent quant aux effets secondaires de la fonction de rappel. À strictement parler, votre solution crée un tableau supplémentaire de nombres naturels (résultats depush
), tandis que la question indique: "sans créer de nouveau tableau".