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", ...]
la source
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", ...]
Vous pouvez utiliser concat
pour fusionner des tableaux:
var arrays = [
["$6"],
["$12"],
["$25"],
["$25"],
["$18"],
["$22"],
["$10"]
];
var merged = [].concat.apply([], arrays);
console.log(merged);
L'utilisation de la apply
méthode de concat
prendra simplement le deuxième paramètre comme un tableau, donc la dernière ligne est identique à ceci:
var merged2 = [].concat(["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]);
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 .
const arrays = [
["$6"],
["$12"],
["$25"],
["$25"],
["$18"],
["$22"],
["$10"]
];
const merge3 = arrays.flat(1); //The depth level specifying how deep a nested array structure should be flattened. Defaults to 1.
console.log(merge3);
concat
cela ne modifie pas le tableau source, donc le merged
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.
function flatten(arr) {
return arr.reduce(function (flat, toFlatten) {
return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
}, []);
}
Usage:
flatten([[1, 2, 3], [4, 5]]); // [1, 2, 3, 4, 5]
flatten([[[1, [1.1]], 2, 3], [4, 5]]); // [1, 1.1, 2, 3, 4, 5]
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 la 1
liaison flat
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:
var oldArray = [[1],[2,3],[4]];
var newArray = Array.prototype.concat.apply([], oldArray);
console.log(newArray); // [ 1, 2, 3, 4 ]
[].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.
var arrays = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]];
arrays = arrays.reduce(function(a, b){
return a.concat(b);
}, []);
Ou, avec ES2015:
arrays = arrays.reduce((a, b) => a.concat(b), []);
[]
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 et core-js@3
(la bibliothèque de babel) l'inclut dans leur bibliothèque polyfill )
const arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
// Flatten 2 levels deep
const arr3 = [2, 2, 5, [5, [5, [6]], 7]];
arr3.flat(2);
// [2, 2, 5, 5, 5, [6], 7];
// Flatten all levels
const arr4 = [2, 2, 5, [5, [5, [6]], 7]];
arr4.flat(Infinity);
// [2, 2, 5, 5, 5, 6, 7];
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 :
const flatten = function(arr, result = []) {
for (let i = 0, length = arr.length; i < length; i++) {
const value = arr[i];
if (Array.isArray(value)) {
flatten(value, result);
} else {
result.push(value);
}
}
return result;
};
flatten(Array(200000).fill([1]));
Il gère très bien les énormes tableaux. Sur ma machine, ce code prend environ 14 ms à exécuter.
flatten(Array(2).fill(Array(2).fill(Array(2).fill([1]))));
Il fonctionne avec des tableaux imbriqués. Ce code produit [1, 1, 1, 1, 1, 1, 1, 1]
.
flatten([1, [1], [[1]]]);
Il n'a aucun problème avec les tableaux d'aplatissement comme celui-ci.
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 .
function flatten(arr) {
return [].concat(...arr)
}
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:
function deepFlatten(arr) {
return flatten( // return shalowly flattened array
arr.map(x=> // with each x in array
Array.isArray(x) // is x an array?
? deepFlatten(x) // if yes, return deeply flattened x
: x // if no, return just x
)
)
}
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.
apply
de cette manière, j'ai supprimé mes commentaires des vôtres. Je pense toujours que l'utilisation apply
/ 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 :
var x = [[1], [2], [3, 4]];
_.flatten(x); // => [1, 2, 3, 4]
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
(ou flatMap
) est exactement ce dont nous avons besoin dans cette situation.
// concat :: ([a],[a]) -> [a]
const concat = (xs,ys) =>
xs.concat (ys)
// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = f => xs =>
xs.map(f).reduce(concat, [])
// id :: a -> a
const id = x =>
x
// flatten :: [[a]] -> [a]
const flatten =
concatMap (id)
// your sample data
const data =
[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]
console.log (flatten (data))
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
// Player :: (String, Number) -> Player
const Player = (name,number) =>
[ name, number ]
// team :: ( . Player) -> Team
const Team = (...players) =>
players
// Game :: (Team, Team) -> Game
const Game = (teamA, teamB) =>
[ teamA, teamB ]
// sample data
const teamA =
Team (Player ('bob', 5), Player ('alice', 6))
const teamB =
Team (Player ('ricky', 4), Player ('julian', 2))
const game =
Game (teamA, teamB)
console.log (game)
// [ [ [ 'bob', 5 ], [ 'alice', 6 ] ],
// [ [ 'ricky', 4 ], [ 'julian', 2 ] ] ]
Ok, disons maintenant que nous voulons imprimer une liste qui montre tous les joueurs qui participeront à game
…
const gamePlayers = game =>
flatten (game)
gamePlayers (game)
// => [ [ 'bob', 5 ], [ 'alice', 6 ], [ 'ricky', 4 ], [ 'julian', 2 ] ]
Si notre flatten
procédure aplatissait également les tableaux imbriqués, nous finirions avec ce résultat poubelle…
const gamePlayers = game =>
badGenericFlatten(game)
gamePlayers (game)
// => [ 'bob', 5, 'alice', 6, 'ricky', 4, 'julian', 2 ]
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é…
// concat :: ([a],[a]) -> [a]
const concat = (xs,ys) =>
xs.concat (ys)
// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = f => xs =>
xs.map(f).reduce(concat, [])
// id :: a -> a
const id = x =>
x
// flatten :: [[a]] -> [a]
const flatten =
concatMap (id)
// deepFlatten :: [[a]] -> [a]
const deepFlatten =
concatMap (x =>
Array.isArray (x) ? deepFlatten (x) : x)
// your sample data
const data =
[0, [1, [2, [3, [4, 5], 6]]], [7, [8]], 9]
console.log (flatten (data))
// [ 0, 1, [ 2, [ 3, [ 4, 5 ], 6 ] ], 7, [ 8 ], 9 ]
console.log (deepFlatten (data))
// [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Là. Vous disposez maintenant d'un outil pour chaque tâche - un pour écraser un niveau d'imbrication flatten
et un pour effacer toute imbrication deepFlatten
.
Vous pouvez peut-être l'appeler obliterate
ou nuke
si vous n'aimez pas le nom deepFlatten
.
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écessaire
L'utilisation d'un combinateur fiable que j'appelle mapReduce
aide à garder les itérations à un minimum; il prend une fonction de cartographie m :: a -> b
, une fonction de réduction r :: (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 sujet
// mapReduce = (a -> b, (b,a) -> b, (b,a) -> b)
const mapReduce = (m,r) =>
(acc,x) => r (acc, m (x))
// concatMap :: (a -> [b]) -> [a] -> [b]
const concatMap = f => xs =>
xs.reduce (mapReduce (f, concat), [])
// concat :: ([a],[a]) -> [a]
const concat = (xs,ys) =>
xs.concat (ys)
// id :: a -> a
const id = x =>
x
// flatten :: [[a]] -> [a]
const flatten =
concatMap (id)
// deepFlatten :: [[a]] -> [a]
const deepFlatten =
concatMap (x =>
Array.isArray (x) ? deepFlatten (x) : x)
// your sample data
const data =
[ [ [ 1, 2 ],
[ 3, 4 ] ],
[ [ 5, 6 ],
[ 7, 8 ] ] ]
console.log (flatten (data))
// [ [ 1. 2 ], [ 3, 4 ], [ 5, 6 ], [ 7, 8 ] ]
console.log (deepFlatten (data))
// [ 1, 2, 3, 4, 5, 6, 7, 8 ]
concat
lui-même ne fait pas exploser la pile, ...
et le apply
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. Haskell concat
( [[a]] -> [a]
) serait appelé flatten
en Javascript et est implémenté comme foldr (++) []
(Javascript: en foldr(concat) ([])
supposant des fonctions curry). Javascript concat
est un appendice étrange ( (++)
en Haskell), qui peut gérer à la fois [a] -> [a] -> [a]
et a -> [a] -> [a]
.
flatMap
, car c'est exactement ce qui concatMap
est: l' bind
instance de la list
monade. concatpMap
est implémenté en tant que foldr ((++) . f) []
. Traduit en Javascript: const flatMap = f => foldr(comp(concat) (f)) ([])
. Ceci est bien sûr similaire à votre implémentation sans comp
.
Une solution pour le cas plus général, lorsque vous pouvez avoir des éléments non-tableau dans votre tableau.
function flattenArrayOfArrays(a, r){
if(!r){ r = []}
for(var i=0; i<a.length; i++){
if(a[i].constructor == Array){
r.concat(flattenArrayOfArrays(a[i], r));
}else{
r.push(a[i]);
}
}
return r;
}
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 ceci flattenArrayOfArrays(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 :
for (var i = 0; i < a.length; i++) {
a[i] = a[i][0];
}
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.
['foo', ['bar']]
à ['f', 'bar']
.
Qu'en est-il de l'utilisation de la reduce(callback[, initialValue])
méthode deJavaScript 1.8
list.reduce((p,n) => p.concat(n),[]);
Ferait le travail.
[[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:
const flatten = arr => arr.reduce(
(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
);
et l'utiliser:
flatten( [1, [2,3], [4,[5,[6]]]] ) // -> [1,2,3,4,5,6]
const flatten = arr => arr.reduce(
(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
);
console.log( flatten([1, [2,3], [4,[5],[6,[7,8,9],10],11],[12],13]) )
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 égale 1
par défaut.
[1, 2, [3, 4]].flat(); // -> [1, 2, 3, 4]
[1, 2, [3, 4, [5, 6]]].flat(); // -> [1, 2, 3, 4, [5, 6]]
[1, 2, [3, 4, [5, 6]]].flat(2); // -> [1, 2, 3, 4, 5, 6]
[1, 2, [3, 4, [5, 6]]].flat(Infinity); // -> [1, 2, 3, 4, 5, 6]
let arr = [1, 2, [3, 4]];
console.log( arr.flat() );
arr = [1, 2, [3, 4, [5, 6]]];
console.log( arr.flat() );
console.log( arr.flat(1) );
console.log( arr.flat(2) );
console.log( arr.flat(Infinity) );
RangeError: Maximum call stack size exceeded
const common = arr.reduce((a, b) => [...a, ...b], [])
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:
// small, reusable auxiliary functions:
const foldl = f => acc => xs => xs.reduce(uncurry(f), acc); // aka reduce
const uncurry = f => (a, b) => f(a) (b);
const concat = xs => y => xs.concat(y);
// the actual function to flatten an array - a self-explanatory one-line:
const flatten = xs => foldl(concat) ([]) (xs);
// arbitrary array sizes (until the heap blows up :D)
const xs = [[1,2,3],[4,5,6],[7,8,9]];
console.log(flatten(xs));
// Deriving a recursive solution for deeply nested arrays is trivially now
// yet more small, reusable auxiliary functions:
const map = f => xs => xs.map(apply(f));
const apply = f => a => f(a);
const isArray = Array.isArray;
// the derived recursive function:
const flattenr = xs => flatten(map(x => isArray(x) ? flattenr(x) : x) (xs));
const ys = [1,[2,[3,[4,[5],6,],7],8],9];
console.log(flattenr(ys));
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.
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.
Voir lodash aplatir , souligner aplatir (peu profond true
)
function flatten(arr) {
return arr.reduce((acc, e) => acc.concat(e), []);
}
function flatten(arr) {
return [].concat.apply([], arr);
}
Testé avec
test('already flatted', () => {
expect(flatten([1, 2, 3, 4, 5])).toEqual([1, 2, 3, 4, 5]);
});
test('flats first level', () => {
expect(flatten([1, [2, [3, [4]], 5]])).toEqual([1, 2, [3, [4]], 5]);
});
Voir lodash aplatir Profond , souligner aplatir
function flattenDeep(arr) {
return arr.reduce((acc, e) => Array.isArray(e) ? acc.concat(flattenDeep(e)) : acc.concat(e), []);
}
Testé avec
test('already flatted', () => {
expect(flattenDeep([1, 2, 3, 4, 5])).toEqual([1, 2, 3, 4, 5]);
});
test('flats', () => {
expect(flattenDeep([1, [2, [3, [4]], 5]])).toEqual([1, 2, 3, 4, 5]);
});
Array.prototype.concat.apply([], arr)
car vous créez un tableau supplémentaire juste pour accéder à la concat
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()
avec Infinity
pour n'importe quelle profondeur de tableau imbriqué.
var arr = [ [1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]], [[1,2,3,4], [1,2,[1,2,3]], [1,2,3,4,5,[1,2,3,4,[1,2,3,4]]]] ];
let flatten = arr.flat(Infinity)
console.log(flatten)
vérifiez ici la compatibilité du navigateur
Une approche Haskellesque
function flatArray([x,...xs]){
return x ? [...Array.isArray(x) ? flatArray(x) : [x], ...flatArray(xs)] : [];
}
var na = [[1,2],[3,[4,5]],[6,7,[[[8],9]]],10];
fa = flatArray(na);
console.log(fa);
Manière ES6:
const flatten = arr => arr.reduce((acc, next) => acc.concat(Array.isArray(next) ? flatten(next) : next), [])
const a = [1, [2, [3, [4, [5]]]]]
console.log(flatten(a))
Méthode ES5 pour la flatten
fonction avec secours ES3 pour les tableaux imbriqués N fois:
var flatten = (function() {
if (!!Array.prototype.reduce && !!Array.isArray) {
return function(array) {
return array.reduce(function(prev, next) {
return prev.concat(Array.isArray(next) ? flatten(next) : next);
}, []);
};
} else {
return function(array) {
var arr = [];
var i = 0;
var len = array.length;
var target;
for (; i < len; i++) {
target = array[i];
arr = arr.concat(
(Object.prototype.toString.call(target) === '[object Array]') ? flatten(target) : target
);
}
return arr;
};
}
}());
var a = [1, [2, [3, [4, [5]]]]];
console.log(flatten(a));
Si vous n'avez que des tableaux avec 1 élément de chaîne:
[["$6"], ["$12"], ["$25"], ["$25"]].join(',').split(',');
fera le travail. Bt qui correspond spécifiquement à votre exemple de code.
['$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(',')
var arrays = [["a"], ["b", "c"]];
Array.prototype.concat.apply([], arrays);
// gives ["a", "b", "c"]
(J'écris simplement ceci comme une réponse distincte, basée sur le commentaire de @danhbear.)
Je recommande une fonction de générateur peu encombrante :
function* flatten(arr) {
if (!Array.isArray(arr)) yield arr;
else for (let el of arr) yield* flatten(el);
}
// Example:
console.log(...flatten([1,[2,[3,[4]]]])); // 1 2 3 4
Si vous le souhaitez, créez un tableau de valeurs aplaties comme suit:
let flattened = [...flatten([1,[2,[3,[4]]]])]; // [1, 2, 3, 4]
...
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 la toString()
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 avec JSON.parse
lequel la chaîne revient à la "vie".
var arr = ["abc",[[[6]]],["3,4"],"2"];
var s = "[" + JSON.stringify(arr).replace(/\[|]/g,'') +"]";
var flattened = JSON.parse(s);
console.log(flattened)
["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:
let arr = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]].flat()
console.log(arr);
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):
let arr = [1,2,[3,4,[5,6]]].flat().flat().flat();
console.log(arr);
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.
Infinity
argument. Comme ça:arr.flat(Infinity)
Utilisation de l'opérateur d'étalement:
const input = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]];
const output = [].concat(...input);
console.log(output); // --> ["$6", "$12", "$25", "$25", "$18", "$22", "$10"]
Ce n'est pas difficile, il suffit d'itérer sur les tableaux et de les fusionner:
var result = [], input = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"]];
for (var i = 0; i < input.length; ++i) {
result = result.concat(input[i]);
}
Il semble que cela ressemble à un travail pour RECURSION!
Code:
var flatten = function(toFlatten) {
var isArray = Object.prototype.toString.call(toFlatten) === '[object Array]';
if (isArray && toFlatten.length > 0) {
var head = toFlatten[0];
var tail = toFlatten.slice(1);
return flatten(head).concat(flatten(tail));
} else {
return [].concat(toFlatten);
}
};
Usage:
flatten([1,[2,3],4,[[5,6],7]]);
// Result: [1, 2, 3, 4, 5, 6, 7]
flatten(new Array(15000).fill([1]))
jette Uncaught RangeError: Maximum call stack size exceeded
et gèle mes devTools pendant 10 secondes
Je l'ai fait en utilisant la récursivité et les fermetures
function flatten(arr) {
var temp = [];
function recursiveFlatten(arr) {
for(var i = 0; i < arr.length; i++) {
if(Array.isArray(arr[i])) {
recursiveFlatten(arr[i]);
} else {
temp.push(arr[i]);
}
}
}
recursiveFlatten(arr);
return temp;
}
L' autre jour, je me moquais des générateurs ES6 et j'ai écrit cet essentiel . Qui contient...
function flatten(arrayOfArrays=[]){
function* flatgen() {
for( let item of arrayOfArrays ) {
if ( Array.isArray( item )) {
yield* flatten(item)
} else {
yield item
}
}
}
return [...flatgen()];
}
var flatArray = flatten([[1, [4]],[2],[3]]);
console.log(flatArray);
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.
juste la meilleure solution sans lodash
let flatten = arr => [].concat.apply([], arr.map(item => Array.isArray(item) ? flatten(item) : item))
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.