Comment étendre un réseau JavaScript existant avec un autre tableau, sans créer un nouveau tableau?

Remarque: Ce n'est pas un double de Comment ajouter quelque chose à un tableau? – le but ici est d'ajouter le contenu entier d'un tableau à l'autre, et de le faire "en place", c'est-à-dire sans copier tous les éléments du tableau étendu.

Il ne semble pas y avoir de moyen d'étendre un réseau de JavaScript existant avec un autre tableau, c'est-à-dire d'imiter la méthode d' extend de Python.

Ce que je veux atteindre est le suivant:

 >>> 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) , mais il crée un nouveau tableau plutôt que d'étendre le premier. Je voudrais un algorithme qui fonctionne efficacement quand a est significativement plus grand que b (c'est-à-dire celui qui ne copie pas a ).

La méthode .push peut prendre plusieurs arguments, donc en utilisant .apply pour passer tous les éléments du second tableau en tant qu'arguments à .push , vous pouvez obtenir le résultat souhaité:

 >>> a.push.apply(a, b) 

Ou peut-être, si vous pensez que c'est plus clair:

 >>> Array.prototype.push.apply(a,b) 

Vous devriez utiliser une technique basée sur la boucle. D'autres réponses sur cette page qui sont basées sur l'utilisation .apply peuvent échouer pour les grands tableaux.

Une implémentation assez concise basée sur la boucle est:

 Array.prototype.extend = function (other_array) { /* you should include a test to check whether other_array really is an array */ other_array.forEach(function(v) {this.push(v)}, this); } 

Vous pouvez alors faire ce qui suit:

 var a = [1,2,3]; var b = [5,4,3]; a.extend(b); 

La réponse de DzinX (using push.apply) et d'autres méthodes basées sur l'application échouent lorsque le tableau que nous ajoutons est grand (les tests montrent que pour moi, il y a plus de 150000 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'appel est dépassée lorsque 'Function.prototype.apply' est appelé avec un grand tableau comme deuxième argument. (Le MDN a une note sur les dangers de dépassement de la taille de la pile d'appel en utilisant Function.prototype.apply – voir la section intitulée "appliquer et intégrer des fonctions")

Pour une comparaison de vitesse avec d'autres réponses sur cette page, vérifiez ce jsperf (grâce à EaterOfCode). L'implémentation basée sur la boucle est similaire à celle de l'utilisation de Array.push.apply, mais tend à être un peu plus lente que Array.slice.apply.

Il est intéressant de noter que si le tableau que vous ajoutez est forEach , la méthode basée pour forEach méthode ci-dessus peut profiter de l'espace libre et surpasser les méthodes basées sur .apply , vérifiez ce jsperf si vous souhaitez tester cela pour vous-même.

En passant, ne soyez pas tenté (comme je l'étais!) De raccourcir encore la mise en œuvre pour chaque tâche:

 Array.prototype.extend = function (array) { array.forEach(this.push, this); } 

Car cela produit des résultats d'ordure! Pourquoi? Parce que Array.prototype.forEach fournit 3 arguments à la fonction qu'il appelle – ce sont: (element_value, element_index, source_array). Tout cela sera poussé sur votre premier tableau pour chaque itération de forEach si vous utilisez "forEach (this.push, this)"!

Pour ceux qui ont simplement recherché "javascript array extension" et obtenu ici, vous pouvez très bien utiliser Array.concat .

 var a = [1, 2, 3]; a = a.concat([5, 4, 3]); 

Concat renverra une copie du nouveau tableau, car le démarreur n'a pas voulu. Mais vous ne vous en soucierez peut-être pas (certainement pour la plupart des utilisations, cela ira bien).


Il y a aussi du bon sucre ES6 pour cela sous la forme de l'opérateur de propagation:

 const a = [1, 2, 3]; const b = [...a, 5, 4, 3]; 

(Également des copies)

Je me sens le plus élégant ces jours-ci:

 arr1.push(...arr2); 

L' article de MDN sur l'opérateur de propagation mentionne cette belle manière sucrée dans ES2015 (ES6):

Une meilleure poussée

Exemple: la poussée est souvent utilisée pour pousser un tableau à la fin d'un tableau existant. Dans ES5, cela se fait souvent comme suit:

 var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // Append all items from arr2 onto arr1 Array.prototype.push.apply(arr1, arr2); 

Dans ES6 avec propagation, cela devient:

 var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1.push(...arr2); 

Notez que arr2 ne peut pas être énorme (maintenez-le sous environ 100 000 éléments), car la pile d'appels débordement, selon la réponse de jcdude.

Si vous souhaitez utiliser jQuery, il y a $ .merge ()

Exemple:

 a = [1, 2]; b = [3, 4, 5]; $.merge(a,b); 

Résultat: a = [1, 2, 3, 4, 5]

J'aime la a.push.apply(a, b) décrite ci-dessus, et si vous le souhaitez, vous pouvez toujours créer une fonction de bibliothèque comme celle-ci:

 Array.prototype.append = function(array) { this.push.apply(this, array) } 

Et l'utiliser comme ça

 a = [1,2] b = [3,4] a.append(b) 

Il est possible de le faire en utilisant splice() :

 b.unshift(b.length) b.unshift(a.length) Array.prototype.splice.apply(a,b) b.shift() // restore b b.shift() // 

Mais en dépit d'être plus laid, ce n'est pas plus rapide que push.apply , du moins pas dans Firefox 3.0. Publié pour l'exhaustivité.

D'abord sur apply () en JavaScript, pour comprendre pourquoi nous utilisons postuler:

La méthode apply () appelle une fonction avec une valeur donnée, et les arguments fournis en tant que tableau.

Vous pouvez facilement imprimer le premier tableau dans l'autre matrice en appliquant. Appliquez le tableau d'acceptation comme des arguments selon les premières lignes, de sorte que vous basiquez uniquement sur les valeurs.
Imaginez que vous avez ces tableaux:

 var a = [1, 2, 3, 4]; var b = [5, 6, 7]; 

Et faites simplement ceci:

 Array.prototype.push.apply(a, b); 

Et le résultat sera:

 a = [1, 2, 3, 4, 5, 6, 7]; 

Même chose dans ES6, peut être fait en utilisant … opérateur comme ceci:

 a.push(...b); //a = [1, 2, 3, 4, 5, 6, 7]; 

Plus court et meilleur mais pas entièrement pris en charge dans tous les navigateurs en ce moment.

Aussi, si vous voulez essentiellement déplacer tout, du tableau b à a et faire le tableau b vide au même moment, vous pouvez le faire.

 while(b.length) { a.push(b.shift()); } 

Et le résultat sera comme suit:

 a = [1, 2, 3, 4, 5, 6, 7]; b = []; 

Vous pouvez créer un polyfill pour étendre comme ci-dessous. Cela ajoutera au tableau; En place et se retourne, afin que vous puissiez chaîner d'autres méthodes.

 if (Array.prototype.extend === undefined) { Array.prototype.extend = function(other) { this.push.apply(this, arguments.length > 1 ? arguments : other); return this; }; } function print() { document.body.innerHTML += [].map.call(arguments, function(item) { return typeof item === 'object' ? JSON.stringify(item) : item; }).join(' ') + '\n'; } document.body.innerHTML = ''; var a = [1, 2, 3]; var b = [4, 5, 6]; print('Concat'); print('(1)', a.concat(b)); print('(2)', a.concat(b)); print('(3)', a.concat(4, 5, 6)); print('\nExtend'); print('(1)', a.extend(b)); print('(2)', a.extend(b)); print('(3)', a.extend(4, 5, 6)); 
 body { font-family: monospace; white-space: pre; } 

Je peux voir de très bonnes réponses, et tout dépend de la taille de votre tableau, de votre exigence et de votre but. On peut faire différentes manières.

Je suggère d'utiliser JavaScript For Loop:

 var a = [1, 2]; var b = [3, 4, 5]; for (i = 0; i < b.length; i++) { a.push(b[i]); } 

console.log(a) sortie sera

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

Ensuite, vous pouvez créer votre propre fonction:

 function extendArray(a, b){ for (i = 0; i < b.length; i++) { a.push(b[i]); } return a; } 

console.log(extendArray(a, b)); La sortie sera

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

Combinaison des réponses …

 Array.prototype.extend = function(array) { if (array.length < 150000) { this.push.apply(this, array) } else { for (var i = 0, len = array.length; i < len; ++i) { this.push(array[i]); }; } } 

Une autre solution pour fusionner plus de deux tableaux

 var a = [1, 2], b = [3, 4, 5], c = [6, 7]; // Merge the contents of multiple arrays together into the first array var mergeArrays = function() { var i, len = arguments.length; if (len > 1) { for (i = 1; i < len; i++) { arguments[0].push.apply(arguments[0], arguments[i]); } } }; 

Ensuite, appelez et imprimez comme suit:

 mergeArrays(a, b, c); console.log(a) 

La sortie sera: Array [1, 2, 3, 4, 5, 6, 7]

La réponse est super simple.

 >>> a = [1, 2] [1, 2] >>> b = [3, 4, 5] [3, 4, 5] >>> SOMETHING HERE (the following code will combine the 2 arrays) a = a.concat(b); >>> a [1, 2, 3, 4, 5] 

Concat agit de manière très similaire à la concaténation de chaîne javascript. Il renverra une combinaison du paramètre que vous mettez dans la fonction concat à la fin du tableau auquel vous appelez la fonction. Le crux est que vous devez attribuer la valeur renvoyée à une variable ou qu'elle se perd. Par exemple

 a.concat(b); <---This does absolutely nothing since it is just returning the combined arrays but it doesn't do anything with it