web-dev-qa-db-ja.com

配列の配列をマージ/フラット化する

私はのようなJavaScriptの配列があります:

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

独立した内部配列をどのようにして1つにマージするのでしょうか。

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

配列をマージするためにconcatを使うことができます。

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

console.log(merged);

applyconcatメソッドを使用すると、2番目のパラメータが配列として使用されるので、最後の行は次のようになります。

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

実験的な Array.prototype.flat() メソッド(まだECMAScript標準の一部ではありません)もありますが、 Edgeや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

これは、n次元配列を平坦化するための新しいJavaScript配列メソッドのいくつかを使用する短い関数です。

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

使用法:

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

これは、シンプルでパフォーマンスの良い機能的な解決策です。

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

必須の混乱はありません。

281
Nikita Volkov

JavascriptのReduce機能を使用すると最も効果的です。

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

または、ES2015の場合:

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

js-fiddle

Mozillaのドキュメント

163
user2668376

ここでの答えの大部分は巨大な(例えば20万要素)配列では動作しません、そしてたとえそれらが動作したとしても、それらは遅いです。 polkovnikov.ph's answer は最高のパフォーマンスを発揮しますが、ディープフラットニングには機能しません。

これは 最速の解決策で、複数レベルのネストを持つ配列でも機能します

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

巨大な配列をうまく扱えます。私のマシンでは、このコードを実行するのに約14ミリ秒かかります。

入れ子になった配列

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

入れ子になった配列で動作します。このコードは[1, 1, 1, 1, 1, 1, 1, 1]を生成します。

ネストレベルが異なる配列

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

このように配列を平坦化しても問題はありません。

64

更新:この解決法は大きな配列では動作しないことがわかった。より良い、より速い解決策を探しています。 この答え をチェックしてください。


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

Isは単にarrを展開し、それを引数としてconcat()に渡します。これにより、すべての配列が1つにまとめられます。 [].concat.apply([], arr)と同等です。

あなたはまた深い平坦化のためにこれを試すことができます:

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

JSBin のデモを参照してください。

この答えで使われているECMAScript 6の要素への参照:


注意:find()やarrow関数のようなメソッドはすべてのブラウザでサポートされているわけではありませんが、今すぐこれらの機能を使用できないという意味ではありません。 Babel - を使うだけでES6コードをES5に変換します。

52

アンダースコア を使用できます。

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

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

一般的な手順により、特定の動作を利用する必要があるたびに複雑さを書き換える必要がなくなります。

concatMap(またはflatMap)は、まさにこの状況で必要なものです。

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

先見の明

そして、はい、あなたはそれを正しく推測しました、それはoneレベルだけを平らにします、それはまさにそれがshould作業

このようなデータセットを想像してください

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

では、gameに参加するすべてのプレーヤーを示す名簿を印刷したいとします。

const gamePlayers = game =>
  flatten (game)

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

flattenプロシージャがネストされた配列もフラット化した場合、このガベージ結果になります…

const gamePlayers = game =>
  badGenericFlatten(game)

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

ローリン・ディープ、ベイビー

ネストされた配列をフラット化したくない場合があるということではありません。それだけがデフォルトの動作ではないはずです。

deepFlattenプロシージャを簡単に作成できます…

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

そこ。これで、ジョブごとにツールがあります。1つのレベルのネストを押しつぶすflattenと、すべてのネストを削除するdeepFlattenです。

名前obliterateが気に入らない場合は、nukeまたはdeepFlattenと呼ぶことができます。


2回繰り返さないでください!

もちろん、上記の実装は賢明で簡潔ですが、.mapに続いて.reduceの呼び出しを使用することは、実際に必要以上の反復を行っていることを意味します

mapReduceを呼び出している信頼できるコンビネーターを使用すると、反復を最小限に抑えることができます。マッピング関数m :: a -> b、還元関数r :: (b,a) ->bを取り、新しい還元関数を返します-このコンビネーターはtransducersの中心です。興味があるなら、 私はそれらについて他の答えを書いた

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

これを正確に行うために、 flat と呼ばれる新しいネイティブECMA 2018メソッドがあります。 

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

より一般的な場合、配列に配列でない要素がある場合の解決策.

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

単一要素配列の配列を平坦化するために、ライブラリをインポートする必要はありません。単純なループが最も簡単で、かつ 最も効率的な の解決策です。

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

それをあなたの非常に異なる問題に合わないので、投票しないでください。この解決策は、最も早くて最も簡単な質問です。

23
Denys Séguret

JavaScript 1.8reduce(callback[, initialValue])メソッドを使うことについてはどうですか?

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

仕事をしますか。

23
rab

機能スタイルのECMAScript 6ソリューション

関数を宣言します。 

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

そしてそれを使う:

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

更新:

最新のブラウザの最新リリースで利用可能なネイティブ関数 Array.prototype.flat() (ES6の提案)についても検討してください。

@(КонстантинВан)と@(Mark Amery)がコメントでそれを述べてくれたことに感謝します。

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

注意してください。 Function.prototype.apply[].concat.apply([], arrays))またはスプレッド演算子([].concat(...arrays))を使用して配列を平坦化すると、関数のすべての引数がスタックに格納されるため、両方とも大きな配列に対してスタックオーバーフローが発生します。

これは、最も重要な要件を相互に比較検討する、関数型のスタックセーフな実装です。

  • 再利用性
  • 読みやすさ
  • 簡潔
  • パフォーマンス

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

カレー形式の小さな矢印関数、関数合成、高階関数に慣れるとすぐに、このコードは散文のようになります。その場合、プログラミングは、副作用が含まれていないため、常に予想どおりに機能する小さな構成要素をまとめるだけで構成されます。

14
user6445533

ES6ワンラインフラット

lodash flattenunderscore flatten(shallow true

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

or

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

でテスト済み

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ワンラインディープフラット

lodash flattenDeepunderscore flattenを参照

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

でテスト済み

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

1つの文字列要素を持つ配列しかない場合

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

仕事をします。特にあなたのコード例と一致するBt。

7

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

N回ネスト配列のES3フォールバックを伴うflatten関数のためのES5方法

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

(私は@danhbearのコメントに基づいて、これを別の回答として書いているだけです。)

7
VasiliNovikov

配列全体をそのまま文字列に変換したいのですが、他の答えとは異なり、JSON.stringifyを使用してtoString()メソッドを使用しないでください。これは望ましくない結果を生み出します。

そのJSON.stringifyの出力では、残っているのはすべての括弧を削除し、結果を再び開始括弧と終了括弧で囲み、結果をJSON.parseで処理することで文字列を "life"に戻します。

  • スピードを犠牲にすることなく、無限にネストした配列を扱うことができます。
  • コンマを含む文字列である配列項目を正しく処理できます。

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

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

console.log(flattened)

  • 多次元配列の文字列/数値のみ(オブジェクトではない)
6
vsync

ハスケレスクアプローチ

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

ES6ジェネレーター 先日/を書いて この要旨 と書いた。を含む...

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

基本的に、元の入力配列をループするジェネレータを作成しています。配列が見つかった場合、 yield * 演算子を再帰と組み合わせて使用​​して、内部配列を継続的に平坦化します。アイテムが配列ではない場合、 yield 単一のアイテムになります。それから ES6 Spread演算子 (別名スプラット演算子)を使ってジェネレータを新しい配列インスタンスにフラットにします。

私はこれの性能をテストしませんでした、しかし私はそれがジェネレータとyield *演算子を使うことのいい単純な例であると思います。

しかし、繰り返しになりますが、私は単に間抜けなので、これを実行するよりパフォーマンスの高い方法があると確信しています。

5
ashwell

再帰とクロージャを使ってそれをしました

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

lodashなしの最良の解決策

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

スペース効率のよい ジェネレータ関数をお勧めします

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

必要に応じて、次のように平坦化された値の配列を作成してください。

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

これはRECURSIONの仕事のように見えます!

  • 複数レベルのネスティングを処理
  • 空の配列と配列以外のパラメータを処理する
  • 突然変異がない
  • 最新のブラウザ機能に依存しません

コード:

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

使用法:

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

それは難しくありません、単に配列を反復処理してそれらをマージするだけです。

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

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

ここでのロジックは、入力配列を文字列に変換してすべての角かっこ([])を削除し、出力を配列に解析することです。これにはES6テンプレート機能を使用しています。

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

現在、これを行うための最善かつ簡単な方法は、このように配列を結合および分割することです。

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

この解決策は複数のレベルで機能し、また厄介です。

デモ

ECMAScript 6のEDIT

ECMAScript 6は標準化されているので、操作[].concat.apply([], arrays);[].concat(...arrays);に変更できます。

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

デモ

編集最も効率的な解決策

問題を解決するための最も効率的な方法はループを使うことです。 "ops/sec"の速度を比較することができます ここ

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

デモ

それが役に立てば幸い

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

要求ごとに、1行を分割することは基本的にこれがあることです。 

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

再帰のない2つの短い解決策を提案します。これらは計算の複雑さの観点からは最適ではありませんが、平均的なケースではうまくいきます。

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

私はこれがハックであることを承知していますが、(任意の深さの)文字列の配列を(コンマなしで)平坦化するために私が知っている最も簡潔な方法は、配列を文字列に変換してから文字列をコンマで分割することです。

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

これは、文字列と数値(整数と浮動小数点)のみを含むネストされた配列の任意の深さで機能するはずです。ただし、数値は処理中に文字列に変換されることに注意してください。これは小さなマッピングで解決できます。

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

もしあなたの配列が整数や文字列だけで構成されているなら、このダーティーハックを使うことができます。

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

FFでは、IEとChromeは他のブラウザをまだテストしていません。

2
EaterOfCode

2次元配列を1行に平坦化するには

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

これは現代のブラウザ用のもう一つの深いフラットです

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

これは、Artif3xによる答えに基づいたTypeScriptのバージョンで、ScalaファンのためのflatMapのボーナス実装です。

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

再帰的な方法のようにするほうがよいので、他の配列の内側にさらに別の配列がある場合は、フィルターをかけた...にすることができます。

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

そして、あなたはそれを好きに呼ぶことができます:

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

そして結果は以下のようになります。

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

素晴らしい解決策を追加するだけです。これを解決するために再帰を使いました。

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

テスト結果: https://codepen.io/ashermike/pen/mKZrWK

1
Asher

次のコードは、深くネストした配列を平坦化します。

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

この質問にES6で答えるだけです。深い配列は次のように仮定します。

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

あなたが知っているか、あなたの配列の深さが7のような数より多くないことを知っているか推測するならば、以下のコードを使用してください:

const flatArray = deepArray.flat(7);

しかし、深い配列の深さがわからない場合や、JavaScriptエンジンがreact-nativeflatのようにJavaScriptCoreをサポートしていない場合は、JavaScriptreduce関数を使用します。

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

両方のメソッドとも以下の結果を返します。

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

Ramda JS flatten を使用できます。 

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

Array.prototype.reduce()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);

関連文書: 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

ネストされた配列の深さに関係なく、 Array.flat()Infinityと一緒に使用できます。

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)

ブラウザで確認する 互換性

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

lodashを使用する場合、そのflattenメソッドを使用できます。 https://lodash.com/docs/4.17.14#flatten

Lodashの良いところは、配列を平坦化するメソッドもあることです:

i)再帰的に: https://lodash.com/docs/4.17.14#flattenDeep

ii)最大nレベルのネスト: https://lodash.com/docs/4.17.14#flattenDepth

例えば

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

私が書いたシンプルなフラット化ユーティリティ

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

私はもともと.reduceメソッドを使って内部配列を平坦化する関数を再帰的に呼び出すことを考えていましたが、深くネストされた配列の中で深くネストされた配列を扱う場合、これはスタックオーバーフローを引き起こす可能性があります。各反復が配列の新しい浅いコピーを作成するので、concatを使用するのも最善の方法ではありません。代わりにできることはこれです。

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

Concatを使って新しい配列を作成するのではなく、再帰的に関数を呼び出すこともしません。

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

1
pizza-r0b

すべてのデータ型で機能する再帰バージョン

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

fooというjavascriptの配列の配列を定義し、javascriptの配列concat組み込みメソッドを使用して、その配列の配列を単一の配列にフラット化します。

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

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

印刷する必要があります:

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

あなたはこれを試すことができます:

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

IE8をサポートする必要があり、したがってreduceやisArrayなどのメソッドを使用できない場合は、考えられる解決策があります。それはあなたが再帰的なアルゴリズムを理解するのを助けるための冗長なアプローチです。

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

特別なjs関数を使わずに簡単な解決法があります。 (還元など)

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

アレイを平坦化する方法

  • es6 flat()を使用する
  • es6 reduce()を使う
  • 再帰を使う
  • 文字列操作を使う

[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

はるかに単純で直接的なもの。深く平らにするオプションがあります。

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

ディープフラット化とオブジェクト指向はどうですか?

[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フラット化:

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

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

_ demo _

_ cdn _


すべての配列要素がInteger、Float、...、またはStringである場合は、次のようにします。 

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

デモ

0
Abdennour TOUMI

ScalaJavascriptでSeq.flattenを複製する方法を探しているユーザーにとって、これはArrayのポン引きです。

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

これはこのように使用することができます:

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

これが私のバージョンです。それはあなたがより多くのシナリオで使うことができる複雑なオブジェクトを平らにすることを可能にします:

入力

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

コード

機能は次のとおりです。

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

使用法  

var output = []

flatten(input, output);

出力

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

0
Tim Hong

ES6のシアーマジック

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

この方法を試してください。

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

array.flat()を使用してください。

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

一番上の答えにリストされているmerge.concat.apply()メソッドを使用するよりはるかに速いこれをする方法があります、そしてより速いことによって私は 数桁以上 より速く意味します。これはあなたの環境がES5のArrayメソッドにアクセスできることを前提としています。

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

これがjsperfのリンクです。 http://jsperf.com/2-dimensional-array-merge

0
Artif3x

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

フラット化がそれほど深くない場合、私はここで大規模配列の解決策を見つけられませんでした。だから、私のバージョン:

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