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

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

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

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

Q&A

解決済

3回答

1341閲覧

js objデータから再度新しいobj形式のデータを作成する

cheche0830

総合スコア187

JavaScript

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

0グッド

0クリップ

投稿2018/11/28 04:41

<html> <body> <script> var data = [ { "id":"aaa", "name":"name1", "attrs":[ { "attr1":"bbb", "attr2":"ccc" } ] }, { "id":"bbb", "name":"name2", "attrs":[{ "attr1":"aaa" }] }, { "id":"ccc", "name":"name3", "attrs":[{ "attr1":"bbb" }] } ]; var Obj = {}; Object.keys(data).forEach(function (key) { var Temps = {}; Temps.id = data[key].id; Temps.name = data[key].name; var attrs = []; Object.keys(data[key].attrs[0]).forEach(function (key2) { var name; Object.keys(data).forEach(function (key3) { if(data[key3].id == data[key].attrs[0][key2]) { name = data[key3].name; } }); attrs.push(data[key].attrs[0][key2]+","+name); Temps.attrs = attrs; }); Obj[key] = Temps; }); console.log(Obj); </script> </body> </html>

このような感じで、
各id内のattrsに記載されている相手先のidの
nameを取得して再構築してobj化するプログラムを書いたのですが、
どうも回りくどいような気がしてまして、
もっとスマートなやり方はございますでしょうか?

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

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

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

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

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

guest

回答3

0

一般的にディープコピーと呼ばれる方法ですね。
JavaScript deep copy」どんなのかをざっくり知りたければこんな感じの検索ワードから記事を読み漁ってください。

お手軽にやりたければJSONを経由するJSON.parse(JSON.stringify(data))でしょう。
ただしJSONはDateTimeやFunction、その他インスタンス系オブジェクトを扱えませんので、
ニッチな値を含めてしまうと動作しないので注意してください。


質問文のコードは3重ネストのループに近い文ですが、4重ネストにはなりますか?
もしなるのであればそもそも欠陥です。
自分で作っても良いのですが、大抵抜けや漏れが出るので有名所のライブラリを使いましょう。

Creates a deep copy of the value which may contain (nested) Arrays and Objects, Numbers, Strings, Booleans and Dates. Functions are assigned by reference rather than copied

なとと書いており、バッチリディープコピーをアピールしています。

勉強の為に自分で作ってみたいというのであれば、
最も威力を発揮するのは再帰関数なので再帰関数を使うようにしましょう。
JavaScriptの「型」の判定について - Qiitaなどの記事を見ながらサクッと作ってみました

JavaScript

1var data = [ 2 {"id": "aaa", "name": "name1", "attrs": [{"attr1": "bbb", "attr2": "ccc"}]}, 3 {"id": "bbb", "name": "name2", "attrs": [{"attr1": "aaa"}]}, 4 {"id": "ccc", "name": "name3", "attrs": [{"attr1": "bbb"}]} 5]; 6// 配列とオブジェクトにだけ対応した手抜きディープコピー 7var deepCopy = it => { 8 if (Object.prototype.toString.call(it) === '[object Array]') { 9 return it.map(deepCopy); 10 } 11 if (Object.prototype.toString.call(it) === '[object Object]') { 12 return Object.keys(it).reduce((obj, key) => { 13 obj[key] = deepCopy(it[key]); 14 return obj; 15 }, {}); 16 } 17 return it; 18} 19 20var data2 = deepCopy(data); 21data2[0].attrs[0].attr1 = 'updated'; 22console.log(data[0].attrs[0].attr1); // bbb 23console.log(data2[0].attrs[0].attr1); // updated

投稿2018/11/28 06:54

miyabi-sun

総合スコア21158

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

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

cheche0830

2018/11/28 07:03

ありがとうございます!! ネストがとっても気になっていたので、穴が開くほど読ませていただきます!
cheche0830

2018/11/28 08:30

再帰関数むずかしいですね・・・.callもなかなかどうして・・・
guest

0

関数がなければ

javascript

1const Obj = JSON.parse(JSON.stringify(data));

関数があるならライブラリを使うのがいいみたいです
参考

投稿2018/11/28 04:45

編集2018/11/28 05:02
papinianus

総合スコア12705

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

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

cheche0830

2018/11/28 07:03

ありがとうございます!
guest

0

ベストアンサー

javascript

1const Obj = JSON.parse(JSON.stringify(data)); 2var tmp={}; 3Obj.forEach(function(x){tmp[x.id]=x.name}); 4Obj.forEach(function(x){ 5 x.attrs.forEach(function(y){ 6 Object.keys(y).forEach(function(z){ 7 y[z]+=","+tmp[y[z]]; 8 }) 9 }); 10}); 11console.log(Obj);

投稿2018/11/28 07:50

yambejp

総合スコア114572

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

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

cheche0830

2018/11/28 07:56

!!!すごいさっぱりしてます!!! ちょっとまだ理解できてませんので解析させていただきます! ありがとうございました!
cheche0830

2018/11/28 08:27 編集

すいません、ひとつ質問なのですが、 いただいたコードは、 私のコードのように Obj[key] = Temps; と明示的にObjに最後格納していないように見えるのですが、 参考にいただいたconsoleではObjにちゃんと入っております。。 Obj.forEachというのは代入しなくても 値が格納されるものなのでしょうか・・・? すいません、的外れなご質問でしたら・・・
yambejp

2018/11/28 09:02

javascriptの代入は基本的に参照渡しなので抜き出した要素を変更すれば 上位のオブジェクトに反映されます var a=[{},{},{}]; var b=0; a.forEach(function(x){ x.num=++b; }); console.log(a); //出力:[ { num: 1 },{ num: 2 },{ num: 3 }]
cheche0830

2018/11/28 09:14

あーーーーそうなんですね!! ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問