web-dev-qa-db-fra.com

Fusionner/aplatir un tableau de tableaux en JavaScript?

J'ai un tableau JavaScript comme:

[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]

Comment pourrais-je fusionner les tableaux internes distincts en un:

["$6", "$12", "$25", ...]
831
Andy

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 méthode apply de concat prendra simplement le deuxième paramètre sous forme de tableau, la dernière ligne est donc identique à celle-ci:

var merged2 = [].concat(["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]);

Il existe également une méthode expérimentale Array.prototype.flat() (ne faisant pas encore partie de la norme ECMAScript) que vous pouvez utiliser pour aplatir les tableaux, bien que elle ne soit pas encore disponible dans Edge ou Node.js .

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

1461
Gumbo

Voici une courte fonction qui utilise certaines des méthodes de tableau JavaScript les plus récentes 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]
408
Noah Freitas

Voici une solution fonctionnelle simple et performante:

var result = [].concat.apply([], [[1],[2,3],[4]]);
console.log(result); // [ 1, 2, 3, 4 ]

Pas de gâchis impératif.

281
Nikita Volkov

Cela 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), []);

js-fiddle

Documents Mozilla

163
user2668376

La plupart des réponses ne fonctionnent pas sur des tableaux énormes (par exemple 200 000 éléments) et même si elles le sont, elles sont lentes. La réponse de polkovnikov.ph a les meilleures performances, mais ne fonctionne pas pour un aplatissement en profondeur.

Voici la solution la plus rapide, qui fonctionne également sur les 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;
};

Exemples

Énormes tableaux

flatten(Array(200000).fill([1]));

Il gère très bien les tableaux énormes. Sur ma machine, ce code prend environ 14 ms à exécuter.

Tableaux imbriqués

flatten(Array(2).fill(Array(2).fill(Array(2).fill([1]))));

Cela fonctionne avec les tableaux imbriqués. Ce code produit [1, 1, 1, 1, 1, 1, 1, 1].

Matrices avec différents niveaux d'imbrication

flatten([1, [1], [[1]]]);

Il n'a aucun problème avec les tableaux aplatissement comme celui-ci.

64

Update: il s'est avéré que cette solution ne fonctionnait 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 étend simplement arr et le passe comme arguments à concat(), qui fusionne tous les tableaux en un. 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 secondaire: les méthodes telles que find() et les fonctions de flèche 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. Il suffit d’utiliser Babel - pour transformer le code ES6 en ES5.

52

Vous pouvez utiliser Souligner :

var x = [[1], [2], [3, 4]];

_.flatten(x); // => [1, 2, 3, 4]
46
Todd Yandell

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))

prévoyance

Et oui, vous l’avez bien deviné, cela n’aplatit que un niveau, ce qui est exactement ce que cela donne {devrait} _

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 procédure flatten aplatissait également les tableaux imbriqués, nous aboutirions à ce résultat inefficace…

const gamePlayers = game =>
  badGenericFlatten(game)

gamePlayers (game)
// => [ 'bob', 5, 'alice', 6, 'ricky', 4, 'julian', 2 ]

rollin 'deep, bébé

Cela ne veut pas dire que, parfois, vous ne voulez pas non plus aplatir les tableaux imbriqués, mais seulement que cela ne devrait pas être le comportement par défaut.

Nous pouvons faire une procédure deepFlatten avec facilité…

// 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 travail: un pour supprimer un niveau d'imbrication, flatten, et un pour effacer toutes les imbrications deepFlatten.

Vous pouvez peut-être l'appeler obliterate ou nuke si vous n'aimez pas le nom deepFlatten.


Ne pas itérer deux fois!

Bien sûr, les implémentations ci-dessus sont intelligentes et concises, mais utiliser un .map suivi d'un appel à .reduce signifie en réalité que nous faisons plus d'itérations que nécessaire.

L'utilisation d'un combinateur fiable que j'appelle mapReduce aide à garder les itérations au minimum; il prend une fonction de mappage 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 de transducteurs; si cela vous intéresse, 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 ]

38
user633183

Il existe une nouvelle méthode native ECMA 2018 appelée flat pour le faire exactement. 

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]]
35
Alister Norris

Une solution pour le cas plus général, lorsque vous pouvez avoir des éléments non-array 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;
}
29
Trindaz

Pour aplatir un tableau de tableaux à un seul élément, vous n'avez pas besoin d'importer de 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 votants: lisez la question, ne cédez pas, cela 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.

23
Denys Séguret

Qu'en est-il de l'utilisation de la méthode reduce(callback[, initialValue]) de JavaScript 1.8

list.reduce((p,n) => p.concat(n),[]);

Ferait le travail.

23
rab

Une autre solution ECMAScript 6 de style fonctionnel:

Déclarez la 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]

METTRE À JOUR:

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.} _

22
diziaq
const common = arr.reduce((a, b) => [...a, ...b], [])
15
YairTawil

Remarque: Lorsque Function.prototype.apply ([].concat.apply([], arrays)) ou l'opérateur spread ([].concat(...arrays)) est utilisé afin d'aplatir un tableau, les deux peuvent provoquer des débordements de pile pour les grands tableaux, car chaque argument d'une fonction est stocké dans la pile.

Voici une implémentation sécurisée de la pile, dans un style fonctionnel, qui met en balance les exigences les plus importantes:

  • réutilisabilité
  • lisibilité
  • concision
  • performance

// 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échées sous forme curry, composition de fonctions et fonctions d'ordre supérieur, ce code se lit comme une 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.

14
user6445533

ES6 One Line Flatten

Voir lodash aplati , soulignement aplati (peu profonde true)

function flatten(arr) {
  return arr.reduce((acc, e) => acc.concat(e), []);
}

ou

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

ES6 One Line Deep Flatten

Voir lodash flattenDeep , soulignement flatten

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]);
});
9
zurfyx

Si vous avez seulement des tableaux avec 1 élément string:

[["$6"], ["$12"], ["$25"], ["$25"]].join(',').split(',');

va faire le travail. Bt qui correspond spécifiquement à votre exemple de code.

7

Façon 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))

Chemin ES5 pour la fonction flatten avec ES3 fallback pour les tableaux imbriqués N-times:

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

7
Artem Gavrysh
var arrays = [["a"], ["b", "c"]];
Array.prototype.concat.apply([], arrays);

// gives ["a", "b", "c"]

(J'écris ceci simplement comme réponse séparée, basée sur le commentaire de @danhbear.)

7
VasiliNovikov

Je préférerais transformer tout le tableau, tel quel, en une chaîne, mais contrairement à d'autres réponses, je le ferais à l'aide de JSON.stringify sans utiliser la méthode toString(), qui produit un résultat non souhaité.

Avec cette sortie JSON.stringify, tout ce qui reste à faire est de supprimer tous les crochets, d’envelopper encore le résultat avec des crochets de début et de fin, et de servir le résultat avec JSON.parse, ce qui ramène la chaîne à "vie".

  • Peut gérer des tableaux imbriqués infinis sans aucun frais de vitesse.
  • Peut correctement gérer les éléments de tableau qui sont des chaînes contenant des virgules.

var arr = ["abc",[[[6]]],["3,4"],"2"];

var s = "[" + JSON.stringify(arr).replace(/\[|]/g,'') +"]";
var flattened = JSON.parse(s);

console.log(flattened)

  • Uniquement pour tableau multidimensionnel de chaînes/nombres (pas d'objets)
6
vsync

Une approche haaskellesque

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

5
Redu

L’autre jour, j’étais en train de jouer avec ES6 Generators et j’ai écrit this Gist . 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 en permanence les tableaux internes. Si l'élément n'est pas un tableau, il ne fait que renvoyer l'élément unique. Puis, à l’aide de l’opérateur ES6 Spread (également appelé opérateur Splat), j’aplanis le générateur en une nouvelle instance de tableau.

Je n’ai pas testé les performances de ce logiciel, mais j’imagine que c’est un bon exemple simple d'utilisation des générateurs et de l'opérateur de rendement *.

Mais encore une fois, j'étais en train de gaffer, alors je suis sûr qu'il existe des moyens plus performants de le faire.

5
ashwell

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

juste la meilleure solution sans lodash

let flatten = arr => [].concat.apply([], arr.map(item => Array.isArray(item) ? flatten(item) : item))
5
Vlad Ankudinov

Je recommande une fonction génératrice 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]
5
le_m

On dirait que cela ressemble à un travail pour RECURSION!

  • Gère plusieurs niveaux d'imbrication
  • Traite les tableaux vides et les paramètres autres que les tableaux
  • N'a pas de mutation
  • Ne repose pas sur les fonctionnalités modernes du navigateur

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

Utilisation:

flatten([1,[2,3],4,[[5,6],7]]);
// Result: [1, 2, 3, 4, 5, 6, 7] 
5
Jai

Ce n'est pas difficile, il suffit de parcourir 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]);
}
4
Niko

La logique ici est de convertir le tableau d'entrée en chaîne et de supprimer tous les crochets ([]) et d'analyser la sortie dans un tableau. J'utilise la fonctionnalité de modèle ES6 pour cela.

var x=[1, 2, [3, 4, [5, 6,[7], 9],12, [12, 14]]];

var y=JSON.parse(`[${JSON.stringify(x).replace(/\[|]/g,'')}]`);

console.log(y)
4
R Santosh Reddy

De nos jours, le meilleur moyen de procéder consiste à joindre et à diviser le tableau de cette manière.

var multipleArrays = [["$6","$Demo"], ["$12",["Multi","Deep"]], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]]

var flattened = multipleArrays.join().split(",")

Cette solution fonctionne avec plusieurs niveaux et est également une solution unique.

DEMO

EDIT pour ECMAScript 6

Comme ECMAScript 6 a été normalisé, vous pouvez modifier l'opération [].concat.apply([], arrays); pour [].concat(...arrays);.

var flattened = [].concat(...input);

DEMO

EDIT La solution la plus efficace

Le moyen le plus efficace de résoudre le problème consiste à utiliser une boucle. Vous pouvez comparer la vitesse "ops/sec" ici

var flattened=[];
for (var i=0; i<input.length; ++i) {
    var current = input[i];
    for (var j=0; j<current.length; ++j)
        flattened.Push(current[j]);
} 

DEMO

J'espère que ça aide

3
Sapikelio
const flatten = array => array.reduce((a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []); 

Par demande, casser la ligne est fondamentalement avoir cela. 

function flatten(array) {
  // reduce traverses the array and we return the result
  return array.reduce(function(acc, b) {
     // if is an array we use recursion to perform the same operations over the array we found 
     // else we just concat the element to the accumulator
     return acc.concat( Array.isArray(b) ? flatten(b) : b);
  }, []); // we initialize the accumulator on an empty array to collect all the elements
}
3
alejandro

Je propose deux solutions courtes sans récursivité. Ils ne sont pas optimaux du point de vue de la complexité informatique, mais fonctionnent bien dans les cas moyens:

let a = [1, [2, 3], [[4], 5, 6], 7, 8, [9, [[10]]]];

// Solution #1
while (a.find(x => Array.isArray(x)))
    a = a.reduce((x, y) => x.concat(y), []);

// Solution #2
let i = a.findIndex(x => Array.isArray(x));
while (i > -1)
{
    a.splice(i, 1, ...a[i]);
    i = a.findIndex(x => Array.isArray(x));
}
3
Tommaso Ognibene

Je suis conscient que c'est hacky, mais la façon la plus succincte d'aplatir un tableau (de n'importe quelle profondeur!) De chaînes (sans virgule!) Consiste à transformer le tableau en chaîne, puis de scinder la chaîne en virgules:

var myArray =[["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]];
var myFlatArray = myArray.toString().split(',');

myFlatArray;
// ["$6", "$12", "$25", "$25", "$18", "$22", "$10", "$0", "$15", "$3", "$75", "$5", "$100", "$7", "$3", "$75", "$5"]

Cela devrait fonctionner sur n'importe quelle profondeur de tableaux imbriqués ne contenant que des chaînes et des nombres (nombres entiers et flottants), avec l'avertissement que les nombres seront convertis en chaînes dans le processus. Ceci peut être résolu avec un peu de mapping:

var myArray =[[[1,2],[3,4]],[[5,6],[7,8]],[[9,0]]];
var myFlatArray = myArray.toString().split(',').map(function(e) { return parseInt(e); });
myFlatArray;
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
2
Flip

si votre tableau est constitué uniquement d'entiers ou de chaînes, vous pouvez utiliser ce hack:

var arr = [345,2,[34],2,[524,[5456]],[5456]];
var flat = arr.toString().split(',');

Works, en FF, IE et Chrome n'ont pas encore testé les autres navigateurs.

2
EaterOfCode

Pour aplatir un tableau à deux dimensions sur une ligne:

[[1, 2], [3, 4, 5]].reduce(Function.prototype.apply.bind(Array.prototype.concat))
// => [ 1, 2, 3, 4, 5 ]
2
Danny Nemer

Voici un autre profond aplatir pour les navigateurs modernes:

function flatten(xs) {
  xs = Array.prototype.concat.apply([], xs);
  return xs.some(Array.isArray) ? flatten(xs) : xs;
};
2
elclanrs

Voici une version en TypeScript basée sur la réponse de artif3x, avec une implémentation supplémentaire de flatMap pour les fans de Scala.

function flatten<T>(items: T[][]): T[] {
  return items.reduce((prev, next) => prev.concat(next), []);
}

function flatMap<T, U>(items: T[], f: (t: T) => U[]): U[] {
  return items.reduce((prev, next) => prev.concat(f(next)), new Array<U>());
}
2
Tim

Il est préférable de le faire de manière récursive, donc si encore un autre tableau à l'intérieur de l'autre tableau peut être filtré ...

const flattenArray = arr =>
  arr.reduce(
    (res, cur) =>
       !Array.isArray(cur) 
       ? res.concat(cur)
       : res.concat(flattenArray(cur)), []);

Et vous pouvez l'appeler comme ceci:

flattenArray([[["Alireza"], "Dezfoolian"], ["is a"], ["developer"], [[1, [2, 3]]]]);

et le résultat ci-dessous:

["Alireza", "Dezfoolian", "is a", "developer", 1, 2, 3]
1
Alireza

Juste pour ajouter aux bonnes solutions. J'ai utilisé la récursivité pour résoudre ce problème.

            const flattenArray = () => {
                let result = [];
                return function flat(arr) {
                    for (let i = 0; i < arr.length; i++) {
                        if (!Array.isArray(arr[i])) {
                            result.Push(arr[i]);
                        } else {
                            flat(arr[i])
                        }
                    }
                    return result;
                }
            }

Résultats du test: https://codepen.io/ashermike/pen/mKZrWK

1
Asher

Le code suivant va aplatir les tableaux profondément imbriqués:

/**
 * [Function to flatten deeply nested array]
 * @param  {[type]} arr          [The array to be flattened]
 * @param  {[type]} flattenedArr [The flattened array]
 * @return {[type]}              [The flattened array]
 */
function flattenDeepArray(arr, flattenedArr) {
  let length = arr.length;

  for(let i = 0; i < length; i++) {
    if(Array.isArray(arr[i])) {
      flattenDeepArray(arr[i], flattenedArr);
    } else {
      flattenedArr.Push(arr[i]);
    }
  }

  return flattenedArr;
}

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

console.log(arr, '=>', flattenDeepArray(arr, [])); // [ 1, 2, [ 3, 4, 5 ], [ 6, 7 ] ] '=>' [ 1, 2, 3, 4, 5, 6, 7 ]

arr = [1, 2, [3, 4], [5, 6, [7, 8, [9, 10]]]];

console.log(arr, '=>', flattenDeepArray(arr, [])); // [ 1, 2, [ 3, 4 ], [ 5, 6, [ 7, 8, [Object] ] ] ] '=>' [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
1
RajaPradhan

Je réponds à cette question simplement avec ES6, en supposant que le tableau en profondeur est:

const deepArray = ['1',[['a'],['b']],[2],[[[['4',[3,'c']]]],[5]]];

Si vous savez ou devinez que la profondeur de vos tableaux ne dépasse pas un nombre tel que 7, utilisez le code ci-dessous:

const flatArray = deepArray.flat(7);

Mais si vous ne connaissez pas la profondeur de vos tableaux profonds ou si votre moteur JavaScript ne supporte pas flat comme react-nativeJavaScriptCore, utilisez la fonction ci-dessous qui est utilisée JavaScriptreduce:

 const deepFlatten = arr =>
         arr.reduce(
           (acc, val) =>
             Array.isArray(val) 
               ? acc.concat(deepFlatten(val)) 
               : acc.concat(val),
             []
         );

Les deux méthodes retournent en dessous du résultat:

["1", "a", "b", 2, "4", 3, "c", 5]
1
AmerllicA

Vous pouvez utiliser Ramda JSaplatir

var arr = [[1,2], [3], [4,5]];
var flattenedArray = R.flatten(arr); 

console.log(flattenedArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

1
Morris S

Vous pouvez aplatir un tableau de tableaux à l'aide de Array.prototype.reduce() et Array.prototype.concat().

var data = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]].reduce(function(a, b) {
  return a.concat(b);
}, []);
console.log(data);

Documents associés: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/concat

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

1
GibboK

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érifier ici pour navigateur compatibilité

1
Code Maniac
let arr = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]];
arr = arr.reduce((a, b) => a.concat(b)); // flattened
1
vdegenne

si vous utilisez lodash, vous pouvez simplement utiliser sa méthode flatten: https://lodash.com/docs/4.17.14#flatten

La bonne chose à propos de lodash est qu’il dispose également de méthodes pour aplatir les tableaux:

i) récursivement: https://lodash.com/docs/4.17.14#flattenDeep

ii) Jusqu'à n niveaux d'imbrication: https://lodash.com/docs/4.17.14#flattenDepth

Par exemple

const _ = require("lodash");
const pancake =  _.flatten(array)
1
tldr

Simple flatten util je l'ai écrit

const flatten = (arr, result = []) => {
    if (!Array.isArray(arr)){
        return [...result, arr];
    }
     arr.forEach((a) => {
         result = flatten(a, result)
    })

    return result
}

console.log(flatten([1,[2,3], [4,[5,6,[7,8]]]])) // [ 1, 2, 3, 4, 5, 6, 7, 8 ]
1
StateLess

À l'origine, je pensais utiliser la méthode .reduce et appeler de manière récursive une fonction pour aplatir les tableaux internes. Toutefois, cela peut entraîner des débordements de pile lorsque vous utilisez un tableau profondément imbriqué de tableaux profondément imbriqués. L'utilisation de concat n'est pas non plus la meilleure solution car chaque itération créera une nouvelle copie superficielle du tableau. Ce que nous pouvons faire à la place est la suivante:

const flatten = arr => {
    for(let i = 0; i < arr.length;) {
        const val = arr[i];
        if(Array.isArray(val)) {
            arr.splice(i, 1, ...val);
        } else {
            i ++;
        }
    }
    return arr;
}

Nous ne créons pas de nouveaux tableaux via concat et nous n'appelons aucune fonction de manière récursive.

http://jsbin.com/firiru/4/edit?js,console

1
pizza-r0b

Version récursive qui fonctionne sur tous les types de données

 /*jshint esversion: 6 */

// nested array for testing
let nestedArray = ["firstlevel", 32, "alsofirst", ["secondlevel", 456,"thirdlevel", ["theinnerinner", 345, {firstName: "Donald", lastName: "Duck"}, "lastinner"]]];

// wrapper function to protect inner variable tempArray from global scope;
function flattenArray(arr) {

  let tempArray = [];

  function flatten(arr) {
    arr.forEach(function(element) {
      Array.isArray(element) ? flatten(element) : tempArray.Push(element);     // ternary check that calls flatten() again if element is an array, hereby making flatten() recursive.
    });
  }

  // calling the inner flatten function, and then returning the temporary array
  flatten(arr);
  return tempArray;
}

// example usage:
let flatArray = flattenArray(nestedArray);
1
sylowgreen

Définissez un tableau de tableaux en javascript appelé foo et aplatissez ce tableau de tableaux en un seul tableau en utilisant la méthode intégrée concat de tableau de javascript:

const foo = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]] 
console.log({foo}); 

const bar = [].concat(...foo) 
console.log({bar});

Devrait imprimer:

{ foo: 
   [ [ '$6' ],
     [ '$12' ],
     [ '$25' ],
     [ '$25' ],
     [ '$18' ],
     [ '$22' ],
     [ '$10' ] ] }
{ bar: [ '$6', '$12', '$25', '$25', '$18', '$22', '$10' ] }
1
kvimalkr55

Pouvez-vous essayer ceci:

[].concat.apply([], myArray);
0
Ben Tahar
Array.prototype.flatten = Array.prototype.flatten || function() {
    return [].reduce.call(this, function(flat, toFlatten) {
        return flat.concat(Array.isArray(toFlatten) ? toFlatten.flatten() : toFlatten);
    },[])
};
0
EVGENY GLUKHOV

Si vous devez prendre en charge IE8 et ne pouvez donc pas utiliser de méthodes telles que reduction ou isArray, voici une solution possible. C'est une approche verbeuse pour vous aider à comprendre l'algorithme récursif.

function flattenArray(a){

    var aFinal = [];

    (function recursiveArray(a){

        var i,
            iCount = a.length;

        if (Object.prototype.toString.call(a) === '[object Array]') {
            for (i = 0; i < iCount; i += 1){
                recursiveArray(a[i]);
            }
        } else {
            aFinal.Push(a);
        }

    })(a);

    return aFinal;

}

var aMyArray = [6,3,4,[12,14,15,[23,24,25,[34,35],27,28],56],3,4];

var result = flattenArray(aMyArray);

console.log(result);
0
Fabio Nolasco

J'ai une solution simple sans utiliser dans une fonction spéciale js. (comme réduire etc)

const input = [[0, 1], [2, 3], [4, 5]]
let flattened=[];

for (let i=0; i<input.length; ++i) {
    let current = input[i];
    for (let j=0; j<current.length; ++j)
        flattened.Push(current[j]);
}
0
Shmulik

Façons de faire un tableau aplati

  • en utilisant Es6 flat ()
  • en utilisant Es6 réduire ()
  • en utilisant la récursivité
  • en utilisant la manipulation de chaîne

[1, [2, [3, [4, [5, [6,7], 8], 9], 10]]] - [1, 2, 3, 4, 5, 6, 7, 8, 9 , dix]

// using Es6 flat() 
let arr = [1,[2,[3,[4,[5,[6,7],8],9],10]]]
console.log(arr.flat(Infinity))

// using Es6 reduce()
let flatIt = (array) => array.reduce(
  (x, y) => x.concat(Array.isArray(y) ? flatIt(y) : y), []
)
console.log(flatIt(arr))

// using recursion
function myFlat(array) {
  let flat = [].concat(...array);
  return flat.some(Array.isArray) ? myFlat(flat) : flat;
}
console.log(myFlat(arr));

// using string manipulation
let strArr = arr.toString().split(','); 
for(let i=0;i<strArr.length;i++)
  strArr[i]=parseInt(strArr[i]);

console.log(strArr)
0
Vahid Akhtar

Beaucoup plus simple et simple; avec option pour aplatir profondément;

const flatReduce = (arr, deep) => {
    return arr.reduce((acc, cur) => {
        return acc.concat(Array.isArray(cur) && deep ? flatReduce(cur, deep) : cur);
    }, []);
};

console.log(flatReduce([1, 2, [3], [4, [5]]], false)); // =>  1,2,3,4,[5]
console.log(flatReduce([1, 2, [3], [4, [5, [6, 7, 8]]]], true)); // => 1,2,3,4,5,6,7,8
0
Jegan S

Qu'en est-il de profond aplatir & orienté objet?

[23, [34, 454], 12, 34].flatten();
// -->   [23,34, 454, 12, 34]

[23, [34, 454,[66,55]], 12, 34].flatten();

// -->  [23, 34, 454, [66,55], 12, 34]

DEEP Flatten:

[23, [34, 454,[66,55]], 12, 34].flatten(true);

// --> [23, 34, 454, 66, 55, 12, 34]

D&EACUTE;MO

CDN


Si tous les éléments du tableau sont Integer, Float, ... ou/et String, procédez comme suit: 

var myarr=[1,[7,[9.2]],[3],90];
eval('myarr=['+myarr.toString()+']');
print(myarr);
// [1, 7, 9.2, 3, 90]

DEMO

0
Abdennour TOUMI

PourScalales utilisateurs recherchant un moyen de répliquerSeq.flattenen Javascript, voici un proxénète de Array:

Array.prototype.flatten = function() {
  return [].concat.apply([], this);
};

qui peut être utilisé de cette façon:

[[12, 3, 5], [1], [], [3, 4]].flatten() // [12, 3, 5, 1, 3, 4]
0
Xavier Guihot

var arrays = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"], ["$0"], ["$15"],["$3"], ["$75"], ["$5"], ["$100"], ["$7"], ["$3"], ["$75"], ["$5"]];
var merged = [].concat.apply([], arrays);
alert(merged);

0
Autumnswind

Voici ma version de celui-ci. Il vous permet d’aplatir un objet compliqué qui pourrait être utilisé dans plusieurs scénarios:

Contribution

var input = {
   a: 'asdf',
   b: [1,2,3],
   c: [[1,2],[3,4]],
   d: {subA: [1,2]}
}

Code

La fonction est comme ça:

function flatten (input, output) {

  if (isArray(input)) {
    for(var index = 0, length = input.length; index < length; index++){
      flatten(input[index], output);
    }
  }
  else if (isObject(input)) {
    for(var item in input){
      if(input.hasOwnProperty(item)){
        flatten(input[item], output);
      }
    }
  }
  else {
    return output.Push(input);
  }
};

function isArray(obj) {
  return Array.isArray(obj) || obj.toString() === '[object Array]';
}

function isObject(obj) {
  return obj === Object(obj);
}

Utilisation  

var output = []

flatten(input, output);

Sortie

["asdf", 1, 2, 3, 1, 2, 3, 4, 1, 2]

0
Tim Hong

Pure magie de l'es6

const flat = A => A.reduce((A, a) => Array.isArray(a) ? [...A, ...flat(a)] : [...A, a], []);
0
Sumer

essayez cette méthode,

arr = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]
concat_arr = arr.concat.apply([], arr)
console.log(concat_arr)

0

const flattenArray = myArray => (myArray.toString().split(','));

console.log(flattenArray([["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]]));

0
Milan Rakos

utilisez arrays.flat ();

 var arrays = [
  ["$6"],
  ["$12"],
  ["$25"],
  ["$25"],
  ["$18"],
  ["$22"],
  ["$10"]
];
arrays.flat();
0
Himanshu Sharma

Pour ce faire, il existe un moyen beaucoup plus rapide que d’utiliser la méthode merge.concat.apply () indiquée dans la première réponse, et je veux dire plus vite que plus de plusieurs ordres de grandeur plus rapidement. Cela suppose que votre environnement a accès aux méthodes Array ES5.

var array2d = [
  ["foo", "bar"],
  ["baz", "biz"]
];
merged = array2d.reduce(function(prev, next) {
    return prev.concat(next);
});

Voici le lien jsperf: http://jsperf.com/2-dimensional-array-merge

0
Artif3x

Solutions ES-Next

  1. Array.from/Set/Array.flat/Array.sort
// 1. remove duplicate item
// 2. flat array
let arr= [["$6", ["$18"]], ["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]];

let result = Array.from(new Set(arr.flat(Infinity)));

console.log(`flat array with unique filter`, result);
// 

// 1. remove duplicate item
// 2. sort by Asc order (munber only)
// 3. flat array

// let arr= [["$6", ["$18"]], ["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]];

let arr= [["6", ["18"]], ["6"], ["12"], ["25"], ["25"], ["18"], ["22"], ["10"]];

let result = Array.from(new Set(arr.flat(Infinity))).map(Number).sort((a,b)=> a > b ? 1: -1);

console.log(`flat array with unique filter & Asc sort`, result);
//
  1. ... spread/Set/Array.flat/Array.sort
// 1. remove duplicate item
// 2. flat array
let arr= [["$6", ["$18"]], ["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]];

let result = [...new Set(arr.flat(Infinity))];

console.log(`flat array with unique filter`, result);
// 

// 1. remove duplicate item
// 2. sort by Asc order(number only)
// 3. flat array

//let arr= [["$6", ["$18"]], ["$6"], ["$12"], ["$25"], ["$25"], ["$18"], ["$22"], ["$10"]];

let arr= [["6", ["18"]], ["6"], ["12"], ["25"], ["25"], ["18"], ["22"], ["10"]];

let result = [...new Set(arr.flat(Infinity))].map(Number).sort((a,b)=> a > b ? 1: -1);

console.log(`flat array with unique filter & Asc sort`, result);
// 

refs

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

0
xgqfrms

Je n'ai pas trouvé ici de solution pour les grands réseaux lorsque l'aplatissement n'est pas profond. Donc, ma version:

function flatten(arr){
    result = []
    for (e of arr)
        result.Push(...e)
    return result
}
0
adsurbum
/**
* flatten an array first level
* @method flatten
* @param array {Array}
* @return {Array} flatten array
*/
function flatten(array) {
  return array.reduce((acc, current) => acc.concat(current), []);
}


/**
* flatten an array recursively
* @method flattenDeep
* @param array {Array}
* @return {Array} flatten array
*/
function flattenDeep(array) {
  return array.reduce((acc, current) => {
    return Array.isArray(current) ? acc.concat(flattenDeep(current)) : acc.concat([current]);
  }, []);
}

/**
* flatten an array recursively limited by depth
* @method flattenDepth
* @param array {Array}
* @return {Array} flatten array
*/
function flattenDepth(array, depth) {
  if (depth === 0) {
    return array;
  }
  return array.reduce((acc, current) => {
    return Array.isArray(current) ? acc.concat(flattenDepth(current, --depth)) : acc.concat([current]);
  }, []);
}
0
alejandro
[1,[2,3],[4,[5,6]]].reduce(function(p, c) {
    return p.concat(c instanceof Array ? 
                    c.reduce(arguments.callee, []) : 
                    [c]); 
}, []);
0
spiderlama