7cc@はてなブログ

JavaScriptとかとか

多次元配列の再帰の記述

追記: 2018年現在は一度flattenしてから処理するのが良いと思います。

記述の方法が、for-loopで書くと1通りだが、イテレートメソッドだと2通りある。
どちらでもよいのだけれど、混ざるので整理。

for-loopとイテレートは完全に同じではないが、その点は割愛します。

例えば以下のような配列をすべて処理したい場合

var array = [1, 2 , [3, [4], 5], 6]
var fn = console.log.bind(console)

for-loopでの再帰。(コード1

function forLoop(array, fn) {
  for (var i=0; i<array.length; i++) {
    Array.isArray(array[i]) ? forLoop(array[i], fn) : fn(array[i])
  }
}

イテレートでの再帰コード2
普通再帰はその関数自体を呼び出すので、その例に倣うとこちらの書き方になる。for-loopと同じ構造。

function eachOuter(array, fn) {
  array.forEach(function(e) {
    Array.isArray(e)? eachOuter(e, fn) : fn(e)
  })
}

しかし、イテレートの再帰はこうも書ける(コード3

function eachInner(array, fn) {
  array.forEach(function internal(e) {
    Array.isArray(e)? e.forEach(internal) : fn(e)
  })
}

配列を直接イテレートするならコード3の書き方になる。(コード4

// fnは外部で宣言してもよいし、直接書いてもよい
array.forEach(function internal(e) {
  Array.isArray(e)? e.forEach(internal) : fn(e)
})

こうしてみると、どちらをベースにするかで書き方が変わるようだ。

  • コード1をベース => コード2
  • コード4をベース => コード3