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

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

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

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

JavaScript

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

Q&A

解決済

3回答

1568閲覧

javaScriptで親子関係のあるのオブジェクトを作る

hikakin

総合スコア15

WordPress

WordPressは、PHPで開発されているオープンソースのブログソフトウェアです。データベース管理システムにはMySQLを用いています。フリーのブログソフトウェアの中では最も人気が高く、PHPとHTMLを使って簡単にテンプレートをカスタマイズすることができます。

JavaScript

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

0グッド

2クリップ

投稿2017/07/13 07:03

###前提・実現したいこと
WP REST API v2で取得したカスタムタクソノミーのJSONデータを、
javaScriptで親子関係のあるのオブジェクトにフォーマットを整えたいのですがどのようにしたらよいのかわかりません。

下記のようなオブジェクトを「整形後」の形にしたいです。
parentの値が0であるオブジェクトがルートの親です。
parentの値は親のオブジェクトのIDと紐付いております。

js

1var before = [ 2 { 3 "id": 1, 4 "parent": 0 5 }, 6 { 7 "id": 2, 8 "parent": 0 9 }, 10 { 11 "id": 3, 12 "parent": 1 13 }, 14 { 15 "id": 4, 16 "parent": 2 17 }, 18 { 19 "id": 5, 20 "parent": 3 21 } 22]

####整形後

js

1var before = [ 2 { 3 "id": 1, 4 "parent": 0, 5 "children": [ 6 { 7 "id": 3, 8 "parent": 1 9 "children": [ 10 { 11 "id": 5, 12 "parent": 3 13 } 14 ] 15 } 16 ] 17 }, 18 { 19 "id": 2, 20 "parent": 0, 21 "children": [ 22 { 23 "id": 4, 24 "parent": 2 25 "children": [] 26 } 27 ] 28 } 29]

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

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

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

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

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

kei344

2017/07/13 15:53

ご自身で試されたコードを質問文に追記し、「何」が「どのように」わからないのか、コードのどの部分で詰まっているのかなどを具体的に追記されたほうが回答が望めると思います。
think49

2017/07/18 01:54

整形後のコードではカンマが足りない為に SyntaxError になります。 また、"id": 4 のオブジェクトには children が存在しますが、"id": 5 にはchildrenが存在しない為に統一性がないオブジェクトとなっています。
guest

回答3

0

ベストアンサー

DOM API 互換コード

設計がDOMと似通っていたので、完全にDOM互換にしてみました。

HTML

1<script src="virtual-dom.js"></script> 2<script> 3'use strict'; 4(function () { 5 function getElementById (elementList, id) { 6 id = String(id); 7 8 for (var i = 0, len = elementList.length, element; i < len; ++i) { 9 element = elementList[i]; 10 11 if (element.id === id) { 12 return element; 13 } 14 } 15 16 return null; 17 } 18 19 var before = [ 20 { 21 "id": 1, 22 "parent": 0 23 }, 24 { 25 "id": 2, 26 "parent": 0 27 }, 28 { 29 "id": 3, 30 "parent": 1 31 }, 32 { 33 "id": 4, 34 "parent": 2 35 }, 36 { 37 "id": 5, 38 "parent": 3 39 }, 40 { 41 "id": 0, 42 "parent": null 43 } 44 ]; 45 46 var elements = before.map(function (object) { 47 var element = new this.Element('p'); 48 49 element.id = object.id; 50 return element; 51 }, VirtualDOM); 52 53 before.forEach(function (object, i) { 54 if (object.parent !== null) { 55 getElementById(elements, object.parent).appendChild(elements[i]); 56 } 57 }); 58 59 var documentElement = getElementById(elements, 0); 60 61 var children = documentElement.children.map(function map (element) { 62 return { 63 parent: element.parentNode ? element.parentNode.id : null, 64 id: element.id, 65 children: element.children.map(map) 66 }; 67 }); 68 69 console.log(elements); 70 console.log(children); 71 console.log(JSON.stringify(children)); 72}()); 73</script>

要件を忠実に再現したコード

DOM互換に拘らず、要件を再現したコード。
ただし、「整形後のコード」では次の部分が異なります。

  • SyntaxError が出ていた部分に , を追加した。
  • 質問文には before[0].children[0].children[0].children が存在せず、before[1].children[0].children === [] が存在する為、整合性が取れない。children が存在する方に統一した。

jsfiddleサンプル。

JavaScript

1'use strict'; 2(function () { 3 function getElementById (elementList, id) { 4 // id = String(id); 5 6 for (var i = 0, len = elementList.length, element; i < len; ++i) { 7 element = elementList[i]; 8 9 if (element.id === id) { 10 return element; 11 } 12 } 13 14 return null; 15 } 16 17 function appendChild (parentObject, childObject) { 18 Array.isArray(parentObject.children) ? parentObject.children.push(childObject) : parentObject.children = [childObject]; 19 } 20 21 var before = [ 22 { 23 "id": 1, 24 "parent": 0 25 }, 26 { 27 "id": 2, 28 "parent": 0 29 }, 30 { 31 "id": 3, 32 "parent": 1 33 }, 34 { 35 "id": 4, 36 "parent": 2 37 }, 38 { 39 "id": 5, 40 "parent": 3 41 } 42 ]; 43 44 var rootObject = {"id": 0}; 45 46 before.forEach(function (object, i) { 47 if (!Array.isArray(object.children)) { 48 object.children = []; 49 } 50 51 appendChild(object.parent !== 0 ? getElementById(before, object.parent) : rootObject, object); 52 }); 53 54 // 期待する整形後のコード 55 var after = [ 56 { 57 "id": 1, 58 "parent": 0, 59 "children": [ 60 { 61 "id": 3, 62 "parent": 1, 63 "children": [ 64 { 65 "id": 5, 66 "parent": 3, 67 "children": [] // 追加した 68 } 69 ] 70 } 71 ] 72 }, 73 { 74 "id": 2, 75 "parent": 0, 76 "children": [ 77 { 78 "id": 4, 79 "parent": 2, 80 "children": [] // 元々、存在している 81 } 82 ] 83 } 84 ]; 85 86 console.log(JSON.stringify(rootObject.children)); // [{"id":1,"parent":0,"children":[{"id":3,"parent":1,"children":[{"id":5,"parent":3,"children":[]}]}]},{"id":2,"parent":0,"children":[{"id":4,"parent":2,"children":[]}]}] 87 console.log(JSON.stringify(after)); // [{"id":1,"parent":0,"children":[{"id":3,"parent":1,"children":[{"id":5,"parent":3,"children":[]}]}]},{"id":2,"parent":0,"children":[{"id":4,"parent":2,"children":[]}]}] 88 console.log(JSON.stringify(rootObject.children) === JSON.stringify(after)); // true 89}());

Re: hikakin さん

投稿2017/07/13 14:08

編集2017/07/18 01:51
think49

総合スコア18166

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

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

think49

2017/07/18 01:52

要件を忠実に再現したコードを追記しました。
guest

0

こんな処理はいかがでしょう。
Object と Array が参照型であることを利用しています。

// 元になるオブジェクト var before = [ { "id": 1, "parent": 0 }, { "id": 2, "parent": 0 }, { "id": 3, "parent": 1 }, { "id": 4, "parent": 2 }, { "id": 5, "parent": 3 } ] // メソッド: 変換する var convert = function (_array) { // 変数 var i = 0; // ループ用 var j = 0; // ループ用 var array = JSON.parse(JSON.stringify(_array)); // (元のオブジェクトを変えたくないならこれをやる) 念のためデータを複製 var objToReturn = {}; // 戻り値 // 2. id:0 のオブジェクトを追加する array.push({id: 0}); // 3. オブジェクトを children に突っ込む L1: for (i = 0; i < array.length; i++) { L2: for (j = 0; j < array.length; j++) { if (array[i].parent == array[j].id) { // children がまだない場合は生成する if (!(array[j].children instanceof Array)) { array[j].children = []; } // children に追加する array[j].children.push(array[i]); break L2; } } } // 4. 戻り値を抜き出す for (i = 0; i < array.length; i++) { if (array[i].id == 0) { objToReturn = array[i].children; } } // 5. return return objToReturn; }; // 実行 var after = convert(before); console.log('答え', after);

投稿2017/07/15 05:51

KoichiAkamine

総合スコア30

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

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

0

ちょっとトリッキーかもです。
クローンを作って参照を残しておき、各children属性の参照を一時配列に作成しながらルート要素以外をフィルタし、最後にクローンの参照を利用してchildren属性の参照を入れ替える、という方法です。

javascript

1var before = [ 2 { 3 'id': 1, 4 'parent': 0 5 }, 6 { 7 'id': 2, 8 'parent': 0 9 }, 10 { 11 'id': 3, 12 'parent': 1 13 }, 14 { 15 'id': 4, 16 'parent': 2 17 }, 18 { 19 'id': 5, 20 'parent': 3 21 } 22]; 23 24var before_clone = before.slice(); 25var children_temp = new Array(before.length+1); 26 27before = before.filter(function (el, _, before) { 28 if (el.parent !== 0) { 29 //ルート要素じゃなければ参照に追加しフィルタ 30 var target = children_temp[el.parent]; 31 if (target === undefined) children_temp[el.parent] = target = []; 32 target.push(el); 33 return false; 34 } else { 35 //ルート要素ならなにもしない 36 return true; 37 } 38}); 39 40//一時配列に収めた参照を、クローンの参照をたどってchildren属性を作成しながら配置。 41before_clone.forEach(function (el, _, _) { 42 if (children_temp[el.id]) { 43 el.children = children_temp[el.id]; 44 } 45}); 46 47 48 49before.toSource(); 50/* 51[{id:1, parent:0, children:[{id:3, parent:1, children:[{id:5, parent:3}]}]}, {id:2, parent:0, children:[{id:4, parent:2}]}] 52*/

 

コードを整理してみた

短くなった。

javascript

1var children_temp = Array.apply( null, Array( before.length + 1 ) ).map( function(){return []} ); // Array.prototype.fill()代替 2 3before.forEach(function ( el, _, _ ) { 4 children_temp[el.parent].push(el); 5}); 6 7before = before.filter(function ( el, _, _ ) { 8 if ( children_temp[el.id].length ) el.children = children_temp[el.id]; 9 return ( el.parent === 0 ); 10});

空の配列をchildrenに許容してくれるなら、ワンライナーいける。

javascript

1before = before.filter( 2 function ( el, _, _ ) { 3 this[el.parent].push(el); 4 el.children = this[el.id]; 5 return ( el.parent === 0 ); 6 }, 7 Array.apply( null, Array( before.length + 1 ) ).map( function(){return []} ) 8);

投稿2017/07/14 01:59

編集2017/07/15 07:41
Lhankor_Mhy

総合スコア36138

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問