J'ai un tableau JavaScript comme:
[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]
Comment pourrais-je fusionner les tableaux internes séparés en un seul comme:
["$6", "$12", "$25", ...]
javascript
arrays
flatten
Andy
la source
la source
reduce
+concat
sont O ((N ^ 2) / 2) où comme réponse acceptée (un seul appel àconcat
) serait au plus O (N * 2) sur un mauvais navigateur et O (N) sur un bon. La solution Denys est également optimisée pour la question réelle et jusqu'à 2 fois plus rapide que la seuleconcat
. Pour lesreduce
gens, c'est amusant de se sentir cool d'écrire du code minuscule, mais par exemple, si le tableau avait 1000 sous-tableaux à un élément, toutes les solutions de réduction + concat feraient 500500 opérations alors que la simple concat ou boucle simple ferait 1000 opérations.[].concat(...array)
array.flat(Infinity)
oùInfinity
est la profondeur maximale à aplatir.Réponses:
Vous pouvez utiliser
concat
pour fusionner des tableaux:L'utilisation de la
apply
méthode deconcat
prendra simplement le deuxième paramètre comme un tableau, donc la dernière ligne est identique à ceci:Il existe également la
Array.prototype.flat()
méthode (introduite dans ES2019) que vous pouvez utiliser pour aplatir les tableaux, bien qu'elle ne soit disponible que dans Node.js à partir de la version 11, et pas du tout dans Internet Explorer .la source
concat
cela ne modifie pas le tableau source, donc lemerged
tableau restera vide après l'appel àconcat
. Mieux vaut dire quelque chose comme:merged = merged.concat.apply(merged, arrays);
var merged = [].concat.apply([], arrays);
semble bien fonctionner pour le mettre sur une seule ligne. edit: comme le montre déjà la réponse de Nikita.Array.prototype.concat.apply([], arrays)
.var merged = [].concat(...arrays)
Voici une fonction courte qui utilise certaines des nouvelles méthodes de tableau JavaScript pour aplatir un tableau à n dimensions.
Usage:
la source
flat
lors du premier appel à la fonction anonyme passée àreduce
. S'il n'est pas spécifié, le premier appel àreduce
lie la première valeur du tableau àflat
, ce qui entraînerait éventuellement la1
liaisonflat
dans les deux exemples.1.concat
n'est pas une fonction.const flatten = (arr) => arr.reduce((flat, next) => flat.concat(next), []);
const flatten = (arr) => arr.reduce((flat, next) => flat.concat(Array.isArray(next) ? flatten(next) : next), []);
Il existe une méthode cachée, qui crée un nouveau tableau sans muter l'original:
la source
[].concat([[1],[2,3],[4]]...)
[[1],[2,3],[4]]
comme résultat. La solution proposée par @Nikita est correcte pour CoffeeScript ainsi que pour JS.[].concat([1],[2,3],[4],...)
....
sont du code réel, pas des points de suspension.Il peut être mieux fait par la fonction de réduction javascript.
Ou, avec ES2015:
js-fiddle
Documents Mozilla
la source
[]
et aucune autre validation n'est nécessaire.arrays.reduce((flatten, arr) => [...flatten, ...arr])
Il existe une nouvelle méthode native appelée flat pour faire exactement cela.
(À la fin de 2019,
flat
est maintenant publié dans la norme ECMA 2019 etcore-js@3
(la bibliothèque de babel) l'inclut dans leur bibliothèque polyfill )la source
La plupart des réponses ici ne fonctionnent pas sur des tableaux énormes (par exemple 200 000 éléments), et même s'ils le font, ils sont lents. La réponse de polkovnikov.ph a les meilleures performances, mais elle ne fonctionne pas pour l'aplatissement en profondeur.
Voici la solution la plus rapide, qui fonctionne également sur des tableaux avec plusieurs niveaux d'imbrication :
Exemples
D'énormes tableaux
Il gère très bien les énormes tableaux. Sur ma machine, ce code prend environ 14 ms à exécuter.
Tableaux imbriqués
Il fonctionne avec des tableaux imbriqués. Ce code produit
[1, 1, 1, 1, 1, 1, 1, 1]
.Tableaux avec différents niveaux d'imbrication
Il n'a aucun problème avec les tableaux d'aplatissement comme celui-ci.
la source
RangeError: Maximum call stack size exceeded
). Pour un tableau de 20 000 éléments, cela prend 2 à 5 millisecondes.Mise à jour: il s'est avéré que cette solution ne fonctionne pas avec les grands tableaux. Si vous cherchez une solution meilleure et plus rapide, consultez cette réponse .
Is se développe simplement
arr
et le passe comme arguments àconcat()
, ce qui fusionne tous les tableaux en un seul. C'est équivalent à[].concat.apply([], arr)
.Vous pouvez également essayer ceci pour un aplatissement profond:
Voir la démo sur JSBin .
Références pour les éléments ECMAScript 6 utilisés dans cette réponse:
Remarque: les méthodes telles
find()
que les fonctions de flèche et ne sont pas prises en charge par tous les navigateurs, mais cela ne signifie pas que vous ne pouvez pas utiliser ces fonctionnalités pour le moment. Utilisez simplement Babel - il transforme le code ES6 en ES5.la source
apply
de cette manière, j'ai supprimé mes commentaires des vôtres. Je pense toujours que l'utilisationapply
/ la diffusion de cette façon est un mauvais conseil, mais comme personne ne s'en soucie ...const flatten = arr => [].concat(...arr)
Vous pouvez utiliser Underscore :
la source
true
pour le deuxième argument .Les procédures génériques signifient que nous n'avons pas à réécrire la complexité chaque fois que nous devons utiliser un comportement spécifique.
concatMap
(ouflatMap
) est exactement ce dont nous avons besoin dans cette situation.prévoyance
Et oui, vous l'avez deviné correctement, cela n'aplatit qu'un niveau, ce qui est exactement comme cela devrait fonctionner
Imaginez un ensemble de données comme celui-ci
Ok, disons maintenant que nous voulons imprimer une liste qui montre tous les joueurs qui participeront à
game
…Si notre
flatten
procédure aplatissait également les tableaux imbriqués, nous finirions avec ce résultat poubelle…rollin 'deep, baby
Cela ne veut pas dire que parfois vous ne voulez pas non plus aplatir les tableaux imbriqués - seulement cela ne devrait pas être le comportement par défaut.
Nous pouvons faire une
deepFlatten
procédure en toute simplicité…Là. Vous disposez maintenant d'un outil pour chaque tâche - un pour écraser un niveau d'imbrication
flatten
et un pour effacer toute imbricationdeepFlatten
.Vous pouvez peut-être l'appeler
obliterate
ounuke
si vous n'aimez pas le nomdeepFlatten
.Ne répétez pas deux fois!
Bien sûr, les implémentations ci-dessus sont intelligentes et concises, mais en utilisant un
.map
suivi d'un appel à.reduce
signifie que nous faisons en fait plus d'itérations que nécessaireL'utilisation d'un combinateur fiable que j'appelle
mapReduce
aide à garder les itérations à un minimum; il prend une fonction de cartographiem :: a -> b
, une fonction de réductionr :: (b,a) ->b
et renvoie une nouvelle fonction de réduction - ce combinateur est au cœur des transducteurs ; si vous êtes intéressé, j'ai écrit d'autres réponses à leur sujetla source
concat
lui-même ne fait pas exploser la pile,...
et leapply
fait (avec de très grands tableaux). Je ne l'ai pas vu. Je me sens juste mal en ce moment.concat
Javascript a une signification différente de celle de Haskell. Haskellconcat
([[a]] -> [a]
) serait appeléflatten
en Javascript et est implémenté commefoldr (++) []
(Javascript: enfoldr(concat) ([])
supposant des fonctions curry). Javascriptconcat
est un appendice étrange ((++)
en Haskell), qui peut gérer à la fois[a] -> [a] -> [a]
eta -> [a] -> [a]
.flatMap
, car c'est exactement ce quiconcatMap
est: l'bind
instance de lalist
monade.concatpMap
est implémenté en tant quefoldr ((++) . f) []
. Traduit en Javascript:const flatMap = f => foldr(comp(concat) (f)) ([])
. Ceci est bien sûr similaire à votre implémentation sanscomp
.Une solution pour le cas plus général, lorsque vous pouvez avoir des éléments non-tableau dans votre tableau.
la source
Object.defineProperty(Array.prototype,'flatten',{value:function(r){for(var a=this,i=0,r=r||[];i<a.length;++i)if(a[i]!=null)a[i] instanceof Array?a[i].flatten(r):r.push(a[i]);return r}});
flattenArrayOfArrays (arr, 10)
ou ceciflattenArrayOfArrays(arr, [1,[3]]);
- ces seconds arguments sont ajoutés à la sortie.r
concaténera réellement les résultats de la récursivité.Pour aplatir un tableau de tableaux à élément unique, vous n'avez pas besoin d'importer une bibliothèque, une simple boucle est à la fois la solution la plus simple et la plus efficace :
Aux downvoters: veuillez lire la question, ne downvote pas car elle ne convient pas à votre problème très différent. Cette solution est à la fois la plus rapide et la plus simple pour la question posée.
la source
['foo', ['bar']]
à['f', 'bar']
.Qu'en est-il de l'utilisation de la
reduce(callback[, initialValue])
méthode deJavaScript 1.8
Ferait le travail.
la source
[[1], [2,3]].reduce( (a,b) => a.concat(b), [] )
est plus sexy.[[1], [2,3]].reduce( (a,b) => a.concat(b))
Une autre solution ECMAScript 6 au style fonctionnel:
Déclarez une fonction:
et l'utiliser:
Considérez également une fonction native Array.prototype.flat () (proposition pour ES6) disponible dans les dernières versions des navigateurs modernes. Merci à @ (Константин Ван) et @ (Mark Amery) l'ont mentionné dans les commentaires.
La
flat
fonction possède un paramètre, spécifiant la profondeur attendue d'imbrication des tableaux, qui est égale1
par défaut.la source
RangeError: Maximum call stack size exceeded
la source
Veuillez noter: quand
Function.prototype.apply
([].concat.apply([], arrays)
) ou l'opérateur d'étalement ([].concat(...arrays)
) est utilisé pour aplatir un tableau, les deux peuvent provoquer des débordements de pile pour les grands tableaux, car chaque argument d'une fonction est stocké sur la pile.Voici une implémentation empilable dans un style fonctionnel qui compare les exigences les plus importantes les unes aux autres:
Dès que vous vous habituez aux petites fonctions flèches au curry, à la composition des fonctions et aux fonctions d'ordre supérieur, ce code se lit comme de la prose. La programmation consiste alors simplement à assembler de petits blocs de construction qui fonctionnent toujours comme prévu, car ils ne contiennent aucun effet secondaire.
la source
const flatten = (arr) => arr.reduce((a, b) => a.concat(b), []);
vous permet d' économiser des déchets visuels et d' expliquer à vos coéquipiers pourquoi vous avez besoin de 3 fonctions supplémentaires et de certains appels de fonction.ES6 One Line Flatten
Voir lodash aplatir , souligner aplatir (peu profond
true
)ou
Testé avec
ES6 One Line Deep Flatten
Voir lodash aplatir Profond , souligner aplatir
Testé avec
la source
Array.prototype.concat.apply([], arr)
car vous créez un tableau supplémentaire juste pour accéder à laconcat
fonction. Les runtime peuvent ou non l'optimiser lors de leur exécution, mais accéder à la fonction sur le prototype ne semble pas plus laid que cela ne l'est déjà dans tous les cas.Vous pouvez utiliser
Array.flat()
avecInfinity
pour n'importe quelle profondeur de tableau imbriqué.vérifiez ici la compatibilité du navigateur
la source
Une approche Haskellesque
la source
Manière ES6:
Méthode ES5 pour la
flatten
fonction avec secours ES3 pour les tableaux imbriqués N fois:la source
Si vous n'avez que des tableaux avec 1 élément de chaîne:
fera le travail. Bt qui correspond spécifiquement à votre exemple de code.
la source
['$4', ["$6"], ["$12"], ["$25"], ["$25", "$33", ['$45']]].join(',').split(',')
[1,4, [45, 't', ['e3', 6]]].toString().split(',')
---- ou -----[1,4, [45, 't', ['e3', 6], false]].toString().split(',')
(J'écris simplement ceci comme une réponse distincte, basée sur le commentaire de @danhbear.)
la source
Je recommande une fonction de générateur peu encombrante :
Si vous le souhaitez, créez un tableau de valeurs aplaties comme suit:
la source
...
pour parcourir le générateur.Je préfère transformer l'ensemble du tableau, tel quel , en une chaîne, mais contrairement à d'autres réponses, je ferais cela en utilisant
JSON.stringify
et non en utilisant latoString()
méthode, qui produit un résultat indésirable.Avec cette
JSON.stringify
sortie, tout ce qui reste est de supprimer tous les crochets, d'envelopper le résultat avec les crochets de début et de fin encore une fois et de servir le résultat avecJSON.parse
lequel la chaîne revient à la "vie".la source
["345", "2", "3,4", "2"]
au lieu de séparer chacune de ces valeurs pour séparer les indices"3,4"
.Vous pouvez également essayer la nouvelle
Array.Flat()
méthode. Cela fonctionne de la manière suivante:La
flat()
méthode crée un nouveau tableau avec tous les éléments de sous-tableau concaténés de façon récursive jusqu'à la couche de profondeur (c'est-à-dire les tableaux à l'intérieur des tableaux)Si vous souhaitez également aplatir des tableaux tridimensionnels ou même supérieurs, vous appelez simplement la méthode plate plusieurs fois. Par exemple (3 dimensions):
Faites attention!
Array.Flat()
est relativement nouvelle. Les navigateurs plus anciens comme ie pourraient ne pas avoir implémenté la méthode. Si vous voulez que votre code fonctionne sur tous les navigateurs, vous devrez peut-être transpiler votre JS vers une version plus ancienne. Recherchez les documents Web MD pour la compatibilité actuelle du navigateur.la source
Infinity
argument. Comme ça:arr.flat(Infinity)
Utilisation de l'opérateur d'étalement:
la source
Ce n'est pas difficile, il suffit d'itérer sur les tableaux et de les fusionner:
la source
Il semble que cela ressemble à un travail pour RECURSION!
Code:
Usage:
la source
flatten(new Array(15000).fill([1]))
jetteUncaught RangeError: Maximum call stack size exceeded
et gèle mes devTools pendant 10 secondesJe l'ai fait en utilisant la récursivité et les fermetures
la source
L' autre jour, je me moquais des générateurs ES6 et j'ai écrit cet essentiel . Qui contient...
Fondamentalement, je crée un générateur qui boucle sur le tableau d'entrée d'origine, s'il trouve un tableau, il utilise l' opérateur yield * en combinaison avec la récursivité pour aplatir continuellement les tableaux internes. Si l'article n'est pas un tableau juste donne le seul élément. Ensuite, en utilisant l' opérateur Spread ES6 (ou splat), j'ai aplati le générateur dans une nouvelle instance de tableau.
Je n'ai pas testé les performances de cela, mais je pense que c'est un bel exemple simple d'utilisation de générateurs et de l'opérateur yield *.
Mais encore une fois, je ne faisais que gaffer, donc je suis sûr qu'il existe des façons plus performantes de le faire.
la source
juste la meilleure solution sans lodash
la source