質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

2327閲覧

JavaScript配列の効率的な整形方法

haruyasu

総合スコア8

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2021/09/26 09:18

Webアプリのコメント返信用の配列を作成するために、JavaScriptで配列の整形をしています。

効率的な整形方法を是非ともご教授頂きたいです。
よろしくお願いいたします。

下記の配列test_listを配列new_test_listに変換したいと思っています。

■変換ルール

parentには親のidが格納されています。
parentに数字が格納されている場合は、親idのchildren配列に要素が格納されます。
子がいる限りどんどんネストしていきます。(コメントの返信を想定)
parentがnullの場合は、親はいません。

const test_list = [ { id: 1, content: 'test1', parent: null, }, { id: 2, content: 'test2', parent: null, }, { id: 3, content: 'test3', parent: 1, }, { id: 4, content: 'test4', parent: 3, }, { id: 5, content: 'test5', parent: 1, }, ]
const new_test_list = [ { id: 1, content: 'test1', children: [ { id: 3, content: 'test3', children: [ { id: 4, content: 'test4', children: [], }, ], }, { id: 5, content: 'test5', children: [], } ], }, { id: 2, content: 'test2', children: [], }, ]

是非ともよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

効率的かは分からんし、データによってはうまくいかないけど、とりあえず

javascript

1let obj = {}; 2for (let o of test_list) { 3 o['children'] = [] 4 obj[o['id']] = o 5} 6 7for (let o of test_list) { 8 if (o['parent'] != null) { 9 let p = o['parent'] 10 delete o['parent'] 11 obj[p]['children'].push(o) 12 } 13} 14 15let new_test_list = []; 16for (let k in obj) { 17 if ('parent' in obj[k]) { 18 delete obj[k]['parent'] 19 new_test_list.push(obj[k]) 20 } 21}

投稿2021/09/26 11:50

takasima20

総合スコア7460

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

haruyasu

2021/09/27 04:04

ありがとうございます。 勉強になります。
guest

0

ベストアンサー

とりま、こないな感じかのう。

javascript

1// 与えられた配列要素から、id と各要素をコピーしたオブジェクトのMapを作成 2const nodesMap = new Map(test_list.map(node => [node.id, {...node, children: [] }])); 3 4// 上記で作成したマップの値である各ノードについて、その親ノードのchildrenに追加するループ 5for (const node of nodesMap.values()) { 6 const parentNode = nodesMap.get(node.parent); 7 if (parentNode) { 8 parentNode.children.push(node); 9 } 10} 11 12// parentがnullのノードの配列としてnew_test_listを得る。 13const new_test_list = Array.from(nodesMap.values()).filter(node => !node.parent); 14 15// 各ノードのparentプロパティが不要になったので削除 16(function deleteParentRecursively(list) { 17 list.forEach(node => { 18 delete node.parent; 19 if (node.children.length) 20 deleteParentRecursively(node.children); 21 }); 22})(new_test_list); 23 24console.log(JSON.stringify(new_test_list, null, 2));

出力結果:

json

1 2[ 3 { 4 'id': 1, 5 'content': 'test1', 6 'children': [ 7 { 8 'id': 3, 9 'content': 'test3', 10 'children': [ 11 { 12 'id': 4, 13 'content': 'test4', 14 'children': [] 15 } 16 ] 17 }, 18 { 19 'id': 5, 20 'content': 'test5', 21 'children': [] 22 } 23 ] 24 }, 25 { 26 'id': 2, 27 'content': 'test2', 28 'children': [] 29 } 30] 31

サンプル


追記:

ひとつ追記しておきます。

上のコードでは、ツリーを構築した後に、各ノードの parent プロパティを削除するために、再帰関数を使って

javascript

1// 各ノードのparentプロパティが不要になったので削除 2(function deleteParentRecursively(list) { 3 list.forEach(node => { 4 delete node.parent; 5 if (node.children.length) 6 deleteParentRecursively(node.children); 7 }); 8})(new_test_list);

としていますが、ここは再帰を使わずとも、もう一度nodesMapの各キーに対する値のすべてを for ・・・ of ・・・ でループさせれば、全ノードを走査できるので、以下でよかったです。

javascript

1// 各ノードのparentプロパティが不要になったので削除 2for (const node of nodesMap.values()) { 3 delete node.parent; 4}

サンプル

(ただし、このツリー構築作業用のマップnodesMapが無くなってしまった後に、ツリーの全ノードをたどるには、deleteParentRecursivelyでやっているような再帰が分かり易いと思います。)

投稿2021/09/26 11:25

編集2021/09/26 16:44
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

haruyasu

2021/09/26 11:43

期待の配列に整形をすることができました。 勉強になります。 ありがとうございました。
退会済みユーザー

退会済みユーザー

2021/09/26 12:23

おおきに〜 実は、完全に白紙から考えてコードを書いたわけではありませんで、 自分がもしこういうのを業務でやらなければならないとしたら、 いかに自分で書かないで済ませるか? を考えてstackoverflowなどをあたったりするんですが、今回の場合も探してみると、こんな質問があり回答も数多く寄せられています。 Build tree array from flat array in javascript https://stackoverflow.com/questions/18017869/build-tree-array-from-flat-array-in-javascript 私の回答は、上記のstackoverflowの回答のうち一番上のベストアンサーのものを参考にしており、マップにオブジェクトではなくMapを使ったり、for ( i=i ; ・・・; ・・・ ) ではなく for ( ・・・ of ・・・ ) を使ったりしています。 他にも、こちらの回答 https://stackoverflow.com/a/34792287 の、listToTree は node module になっており、これを使うと一発でした。 https://codesandbox.io/s/361417-si-zygg7 ただし、ツリー構築後のparentプロパティ削除まではやってくれないので、それは自分でやらないとですが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問