###前提・実現したいこと
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ページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/07/18 01:54
回答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総合スコア18189
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
総合スコア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総合スコア37140
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。