なんとなくArray.prototype.forEachやjQueryのeachを使って再帰関数を回していたのですが、「JavaScript で forEach を使うのは最終手段」という記事を読み、少し考えを改めてみようと思いました。
しかしparent_id
というプロパティを持つフラットなデータを読み込み、それをツリー型にしてみたいと思った時、あれ?と考え込みました。
うーん、forEachつかわず再帰処理させつつデータを作り直すってどうやるんだ・・・
とりあえず何も考えず書いたコード
let func = (obj) => {
obj.items = Object.assign([], master_categories.filter(category =>
category.parent_id === obj.category_id))
obj.items.forEach(func)
}
let categories = Object.assign([], master_categories.filter(category => !category.parent_id))
categories.forEach(func)
//読みにくいかもですが、filter()は実体参照するのでassign()でオブジェクトを複製してます
Array.prototype.mapを使う
forEachよりはマシなのだろうか?
本来はこんな使い方をする関数ではなさそうですが、ひとまずはperlっぽくmapを使うことに。
let func = (obj) => {
let robj = Object.assign({}, obj)
robj.items = master_categories.filter(category =>
category.parent_id && category.parent_id === robj.category_id).map(func)
return robj
}
let categories = master_categories.filter(category => !category.parent_id).map(func)
もっと賢いやり方がありそうですが、ひとまずこれで妥協することに。
追記
一応それっぽいですが、なにか優位だと言える証拠をみつけたかったのでGoogle(他力)にすがってみました。
参考:JavaScript — Map vs. ForEach(codeburst.io)
このサイトの検証結果ではforEachはmapより70%も遅いという結果がでたそうです。