it-swarm.com.de

Array von Arrays in JavaScript zusammenführen/reduzieren

Ich habe ein JavaScript-Array wie:

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

Wie würde ich die einzelnen inneren Arrays zu einem wie dem folgenden zusammenführen:

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

Sie können concat verwenden, um Arrays zusammenzuführen:

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

console.log(merged);

Wenn Sie die apply-Methode von concat verwenden, wird der zweite Parameter nur als Array verwendet. Die letzte Zeile ist also identisch mit dieser:

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

Es gibt auch eine experimentelle Array.prototype.flat() -Methode (noch nicht Teil des ECMAScript-Standards), mit der Sie die Arrays reduzieren können, obwohl in Edge oder Node.js noch nicht verfügbar ist.

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

Hier ist eine kurze Funktion, die einige der neueren JavaScript-Array-Methoden zum Reduzieren eines n-dimensionalen Arrays verwendet.

function flatten(arr) {
  return arr.reduce(function (flat, toFlatten) {
    return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
  }, []);
}

Verwendungszweck:

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

Hier ist eine einfache und performante Funktionslösung:

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

Kein zwingendes Chaos.

281
Nikita Volkov

Dies kann am besten durch die Funktion zum Reduzieren von Javascript erfolgen.

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

Oder mit ES2015:

arrays = arrays.reduce((a, b) => a.concat(b), []);

js-Geige

Mozilla-Dokumente

163
user2668376

Die meisten Antworten hier funktionieren nicht für große Arrays (z. B. 200 000 Elemente), und selbst wenn sie es tun, sind sie langsam. Die Antwort von polkovnikov.ph hat die beste Leistung, funktioniert aber nicht für tiefe Abflachung.

Hier ist die schnellste Lösung, die auch auf Arrays mit mehreren Verschachtelungsebenen funktioniert:

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

Beispiele

Riesige Arrays

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

Es verarbeitet sehr gut große Arrays. Auf meinem Rechner dauert dieser Code etwa 14 ms.

Verschachtelte Arrays

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

Es funktioniert mit verschachtelten Arrays. Dieser Code erzeugt [1, 1, 1, 1, 1, 1, 1, 1].

Arrays mit unterschiedlichen Verschachtelungsstufen

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

Es hat keine Probleme mit dem Abflachen von Arrays wie diesem.

64

Update: Es stellte sich heraus, dass diese Lösung nicht mit großen Arrays funktioniert. Wenn Sie nach einer besseren, schnelleren Lösung suchen, überprüfen Sie diese Antwort .


function flatten(arr) {
  return [].concat(...arr)
}

Wird einfach arr erweitert und als Argumente an concat() übergeben, die alle Arrays zu einem Array zusammenführt. Es ist äquivalent zu [].concat.apply([], arr).

Sie können dies auch zur Tiefenreduzierung versuchen:

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

Siehe Demo zu JSBin .

Verweise auf ECMAScript 6-Elemente, die in dieser Antwort verwendet werden:


Anmerkung: Methoden wie find() und Pfeilfunktionen werden nicht von allen Browsern unterstützt. Dies bedeutet jedoch nicht, dass Sie diese Funktionen derzeit nicht verwenden können. Verwenden Sie einfach Babel - es wandelt ES6-Code in ES5 um.

52

Sie können Unterstrich verwenden:

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

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

Generische Prozeduren bedeuten, dass wir die Komplexität nicht jedes Mal neu schreiben müssen, wenn wir ein bestimmtes Verhalten anwenden müssen.

concatMap (oder flatMap) ist genau das, was wir in dieser Situation brauchen.

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

voraussicht

Und ja, Sie haben es richtig geraten, es flacht nur eine Ebene ab, und genau so funktioniert es sollte

Stellen Sie sich einen Datensatz wie diesen vor

// 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, jetzt sagen wir, wir wollen eine Liste drucken, die alle Spieler zeigt, die an game teilnehmen werden ...

const gamePlayers = game =>
  flatten (game)

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

Wenn unsere flatten -Prozedur auch verschachtelte Arrays reduziert, würden wir dieses Müllergebnis erhalten ...

const gamePlayers = game =>
  badGenericFlatten(game)

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

rollt tief, Baby

Das soll nicht heißen, dass Sie manchmal auch verschachtelte Arrays nicht reduzieren möchten - nur sollte dies nicht das Standardverhalten sein.

Wir können mit Leichtigkeit eine deepFlatten Prozedur machen ...

// 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 ]

Dort. Jetzt haben Sie für jeden Job ein Werkzeug - eines zum Quetschen einer Verschachtelungsebene, flatten, und eines zum Löschen aller Verschachtelungen deepFlatten.

Vielleicht kannst du es obliterate oder nuke nennen, wenn dir der Name deepFlatten nicht gefällt.


Wiederholen Sie nicht zweimal!

Natürlich sind die obigen Implementierungen clever und präzise, ​​aber die Verwendung von .map Gefolgt von einem Aufruf von .reduce Bedeutet, dass wir tatsächlich mehr Iterationen als nötig durchführen

Mit einem vertrauenswürdigen Kombinator, den ich mapReduce aufrufe, können Sie die Iterationen auf ein Minimum beschränken. es benötigt eine Zuordnungsfunktion m :: a -> b, eine Reduzierungsfunktion r :: (b,a) ->b und gibt eine neue Reduzierungsfunktion zurück - dieser Kombinator ist das Herzstück von Wandlern; Wenn Sie interessiert sind, Ich habe andere Antworten darüber geschrieben

// 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 ]
39
user633183

Es gibt eine neue native ECMA 2018-Methode namens flat , um dies genau zu tun. 

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

Eine Lösung für den allgemeineren Fall, wenn sich in Ihrem Array einige Nicht-Array-Elemente befinden.

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

Um ein Array von Einzelelement-Arrays zu vereinfachen, müssen Sie keine Bibliothek importieren. Eine einfache Schleife ist sowohl die einfachste als auch effizienteste Lösung:

for (var i = 0; i < a.length; i++) {
  a[i] = a[i][0];
}

An Downvoter: Bitte lesen Sie die Frage, nicht abwärts, weil sie nicht zu Ihrem ganz anderen Problem passt. Diese Lösung ist für die gestellte Frage sowohl die schnellste als auch die einfachste.

23
Denys Séguret

Was ist mit der reduce(callback[, initialValue]) Methode von JavaScript 1.8

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

Würde den Job machen.

23
rab

Eine weitere ECMAScript 6-Lösung im funktionalen Stil:

Deklarationsfunktion: 

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

und benutze es:

flatten( [1, [2,3], [4,[5,[6]]]] ) // -> [1,2,3,4,5,6]

UPDATE:

Betrachten Sie auch eine native Funktion Array.prototype.flat () (Vorschlag für ES6), die in den letzten Versionen moderner Browser verfügbar ist.

Danke an @ (Константин Ван) und @ (Mark Amery) erwähnte es in den Kommentaren.

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

Bitte beachten Sie: Wenn Function.prototype.apply ([].concat.apply([], arrays)) oder der Spread-Operator ([].concat(...arrays)) verwendet wird, um ein Array zu reduzieren, können beide zu Stapelüberläufen bei großen Arrays führen, da jedes Argument einer Funktion im Stack gespeichert ist.

Hier ist eine stapelsichere Implementierung im funktionalen Stil, die die wichtigsten Anforderungen gegeneinander abwägt:

  • wiederverwendbarkeit
  • lesbarkeit
  • prägnanz
  • 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));

Sobald Sie sich an kleine Pfeilfunktionen in der aktuellen Form, Funktionszusammenstellung und Funktionen höherer Ordnung gewöhnt haben, liest sich dieser Code wie Prosa. Die Programmierung besteht dann lediglich aus kleinen Bausteinen, die immer wie erwartet funktionieren, da sie keine Nebenwirkungen enthalten.

14
user6445533

ES6 Eine Linie abgeflacht

Siehe lodash flatten , Unterstriche (flach true)

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

oder

function flatten(arr) {
  return [].concat.apply([], arr);
}

Getestet mit

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

Siehe lodash flattenDeep , Unterstrich flatten

function flattenDeep(arr) {
  return arr.reduce((acc, e) => Array.isArray(e) ? acc.concat(flattenDeep(e)) : acc.concat(e), []);
}

Getestet mit

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

Wenn Sie nur Arrays mit einem String-Element haben:

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

wird die Arbeit machen. Bt, das speziell zu Ihrem Codebeispiel passt.

7

ES6 Weg:

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

ES5-Weg für flatten-Funktion mit ES3-Fallback für N-fach geschachtelte Arrays:

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"]

(Ich schreibe dies nur als separate Antwort, basierend auf dem Kommentar von @danhbear.)

7
VasiliNovikov

Ich würde lieber das gesamte Array, so wie es ist, in eine Zeichenfolge umwandeln, aber im Gegensatz zu anderen Antworten würde ich dies mit JSON.stringify und nicht mit der toString()-Methode tun, die ein unerwünschtes Ergebnis erzeugt.

Mit dieser JSON.stringify-Ausgabe müssen Sie nur noch alle Klammern entfernen, das Ergebnis erneut mit Start- und Endeklammern umschließen und das Ergebnis mit JSON.parse übergeben, wodurch die Zeichenfolge wieder "lebendig" wird.

  • Kann unbegrenzt verschachtelte Arrays ohne Geschwindigkeitskosten verarbeiten.
  • Kann Array-Elemente, bei denen es sich um Zeichenfolgen handelt, die Kommas enthalten, richtig behandeln.

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

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

console.log(flattened)

  • Nur für mehrdimensionale Arrays von Strings/Zahlen (keine Objekte)
6
vsync

Ein Haskellesque-Ansatz

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

Ich habe neulich mit ES6 Generators vermasselt und schrieb this Gist . Was beinhaltet...

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

Im Grunde erstelle ich einen Generator, der das ursprüngliche Eingabearray durchläuft. Wenn er ein Array findet, verwendet er den Operator yield * in Kombination mit Rekursion, um die internen Arrays kontinuierlich zu glätten. Wenn es sich bei dem Element nicht um ein Array handelt, wird nur das Einzelelement ergibt . Dann verwende ich den Generator mit dem ES6 Spread-Operator (aka Splat-Operator) in eine neue Array-Instanz.

Ich habe die Leistung nicht getestet, aber ich schätze, es ist ein schönes einfaches Beispiel für die Verwendung von Generatoren und des Yield-Operators.

Aber ich habe einfach nur vermasselt, also bin ich sicher, dass es mehr Möglichkeiten gibt, dies zu tun.

5
ashwell

Ich habe es mit Rekursion und Schließungen gemacht

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

einfach die beste Lösung ohne lodash

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

Ich empfehle eine platzsparende Generatorfunktion :

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

Erstellen Sie bei Bedarf ein Array mit reduzierten Werten wie folgt:

let flattened = [...flatten([1,[2,[3,[4]]]])]; // [1, 2, 3, 4]
5
le_m

Es sieht aus wie ein Job für RECURSION!

  • Behandelt mehrere Schachtelungsebenen
  • Behandelt leere Arrays und Nicht-Array-Parameter
  • Hat keine mutation
  • Verlässt sich nicht auf moderne Browserfunktionen

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

Verwendungszweck:

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

Das ist nicht schwer, man muss nur die Arrays durchlaufen und sie zusammenführen:

var result = [], input = [["$6"], ["$12"], ["$25"], ["$25"], ["$18"]];

for (var i = 0; i < input.length; ++i) {
    result = result.concat(input[i]);
}
4
Niko

Die Logik hier besteht darin, das Eingabearray in einen String zu konvertieren und alle Klammern ([]) zu entfernen und die Ausgabe in das Array zu parsen. Ich verwende dazu die ES6-Vorlagenfunktion.

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

Heutzutage ist dies der beste und einfachste Weg, das Array zu verbinden und zu teilen.

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(",")

Diese Lösung arbeitet mit mehreren Ebenen und ist auch online.

DEMO

EDIT für ECMAScript 6

Da ECMAScript 6 standardisiert wurde, können Sie die Operation [].concat.apply([], arrays); für [].concat(...arrays); ändern.

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

DEMO

BEARBEITEN Effizienteste Lösung

Der effizienteste Weg, das Problem zu lösen, ist die Verwendung einer Schleife. Sie können die Geschwindigkeit "ops/sec" vergleichen hier

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

Ich hoffe es hilft

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

Je nach Anforderung besteht das Prinzip darin, die eine Zeile aufzuschlüsseln. 

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

Ich schlage zwei kurze Lösungen ohne Rekursion vor. Sie sind in Bezug auf die rechnerische Komplexität nicht optimal, funktionieren jedoch im Durchschnitt gut:

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

Ich bin mir dessen bewusst, dass dies hackig ist, aber die prägnanteste Art, ein Array (von beliebiger Tiefe!) Von Strings (ohne Kommas!) Zu glätten, besteht darin, das Array in einen String umzuwandeln und dann den String in Kommas zu teilen:

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"]

Dies sollte für jede Tiefe verschachtelter Arrays funktionieren, die nur Strings und Zahlen (Ganzzahlen und Fließpunkte) enthält, mit der Einschränkung, dass Zahlen im Prozess in Strings konvertiert werden. Dies kann mit einem kleinen Mapping gelöst werden:

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

Es ist besser, es auf rekursive Weise zu tun, wenn also noch ein Array innerhalb des anderen Arrays gefiltert leicht sein kann ...

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

Und du kannst es so nennen:

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

und das Ergebnis ist wie folgt:

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

wenn Ihr Array nur aus ganzen Zahlen oder Strings besteht, können Sie diesen schmutzigen Hack verwenden:

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

Works, FF, IE und Chrome haben die anderen Browser noch nicht getestet.

2
EaterOfCode

So reduzieren Sie ein zweidimensionales Array in einer Zeile:

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

Hier ist eine weitere tiefe Abflachung für moderne Browser:

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

Hier ist eine Version in TypeScript, die auf der Antwort von artif3x basiert, mit einer Bonusimplementierung von flatMap für Scala-Fans.

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

Einfach um die tollen Lösungen hinzuzufügen. Ich habe Rekursion verwendet, um das zu lösen.

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

Testergebnisse: https://codepen.io/ashermike/pen/mKZrWK

1
Asher

Der folgende Code reduziert tief verschachtelte Arrays:

/**
 * [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

Ich beantworte diese Frage nur mit ES6. Angenommen, das tiefe Array ist:

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

Wenn Sie wissen oder vermuten, dass die Tiefe Ihrer Arrays nicht mehr als eine Zahl wie 7 ist, verwenden Sie den folgenden Code:

const flatArray = deepArray.flat(7);

Wenn Sie jedoch nicht die Tiefe Ihrer tiefen Arrays kennen oder Ihre JavaScript-Engine flat nicht unterstützt, wie react-nativeJavaScriptCore, verwenden Sie die unten stehende Funktion, die JavaScriptreduce-Funktion verwendet:

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

Beide Methoden geben das Ergebnis zurück:

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

Sie können Ramda JSflatten verwenden. 

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

Sie können ein Array von Arrays mithilfe von Array.prototype.reduce() und Array.prototype.concat() reduzieren.

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

Zugehörige Dokumente: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/concat

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

1
GibboK

Sie können Array.flat() mit Infinity für jede Tiefe des verschachtelten Arrays verwenden.

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)

hier nach Browser Kompatibilität suchen 

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

wenn Sie lodash verwenden, können Sie einfach die flatten -Methode verwenden: https://lodash.com/docs/4.17.14#flatten

Das Schöne an lodash ist, dass es auch Methoden gibt, um die Arrays zu reduzieren:

i) rekursiv: https://lodash.com/docs/4.17.14#flattenDeep

ii) bis zu n Verschachtelungsebenen: https://lodash.com/docs/4.17.14#flattenDepth

Zum Beispiel

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

Einfache Abflachung, die ich geschrieben habe

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

Ursprünglich dachte ich daran, die .reduce-Methode zu verwenden und rekursiv eine Funktion zum Abflachen der inneren Arrays aufzurufen. Dies kann jedoch zu Stapelüberläufen führen, wenn Sie mit einem tief verschachtelten Array tief verschachtelter Arrays arbeiten. Die Verwendung von concat ist auch nicht der beste Weg, da bei jeder Iteration eine neue oberflächliche Kopie des Arrays erstellt wird. Was wir stattdessen tun können, ist folgendes:

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

Wir erstellen keine neuen Arrays über concat und rufen keine Funktionen rekursiv auf.

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

1
pizza-r0b

Rekursive Version, die für alle Datentypen funktioniert

 /*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

Definieren Sie ein Array von Arrays in Javascript mit dem Namen foo und glätten Sie dieses Array von Arrays in ein einzelnes Array mit der eingebauten Array Concat-Methode von Javascript:

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

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

Sollte drucken:

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

Kannst du das versuchen:

[].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

Wenn Sie IE8 unterstützen müssen und daher keine Methoden wie beispielsweise "verkleinern" oder "isArray" verwenden können, finden Sie hier eine mögliche Lösung. Es ist eine verbose Methode, die Ihnen hilft, den rekursiven Algorithmus zu verstehen.

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

Ich habe eine einfache Lösung, ohne eine spezielle js-Funktion zu verwenden. (wie reduzieren 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

Möglichkeiten zum Abflachen des Arrays

  • mit Es6 flat ()
  • mit Es6 redu ()
  • mit Rekursion
  • mit String-Manipulation

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

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

Viel einfacher und unkomplizierter; mit Option zum Abflachen;

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

Was ist mit tiefen Abflachungen & objektorientiertem?

[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]

DEMO

CDN


Wenn alle Array-Elemente Integer, Float, ... oder/und String sind, führen Sie diesen Trick aus: 

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

DEMO

0
Abdennour TOUMI

FürScalaBenutzer, die nach einem Weg suchen,Seq.flattenin Javascript zu replizieren, ist hier ein Zuhälter von Array:

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

was kann so verwendet werden:

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

Hier ist meine Version davon. Sie können ein kompliziertes Objekt abflachen, das in weiteren Szenarien verwendet werden könnte:

Eingabe

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

Code

Die Funktion ist wie folgt:

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

Verwendungszweck  

var output = []

flatten(input, output);

Ausgabe

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

0
Tim Hong

Bloße Magie von ES6

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

probiere diese Methode,

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

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

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

0
Milan Rakos

benutze arrays.flat ();

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

Es gibt einen viel schnelleren Weg, dies zu tun, als die in der obersten Antwort aufgeführte Methode merge.concat.apply (), und mit schneller meine ich mehr als um mehrere Größenordnungen schneller. Dies setzt voraus, dass Ihre Umgebung auf die ES5-Array-Methoden zugreifen kann.

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

Hier ist der jsperf-Link: http://jsperf.com/2-dimensional-array-merge

0
Artif3x

ES-Next-Lösungen

  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. ... verbreiten/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

Ich habe hier keine Lösung für große Arrays gefunden, wenn das Abflachen nicht tief ist. Also meine 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