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

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

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

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

Q&A

解決済

2回答

409閲覧

オブジェクトの一部マージ

eeengineeeeeeer

総合スコア15

JavaScript

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

0グッド

0クリップ

投稿2019/08/02 03:18

オブジェクトの一部をマージしたい場合にどうすればいいか教えていただきたいです。

javascript

1const item = { 2 fruits: { 3 status :"B", 4 apple: { 5 color: "red" 6 }, 7 banana: { 8 color: "yellow" 9 }, 10 strawberry: { 11 color: "red" 12 } 13 } 14}; 15

javascript

1const item2 = { 2 fruits: { 3 id: 21, 4 status :"C", 5 apple: { 6 id: 13, 7 color: "blue" 8 }, 9 banana: { 10 id: 12, 11 color: "green" 12 }, 13 strawberry: { 14 id: 17, 15 color: "red" 16 } 17 } 18};

このような構造似た2つのオブジェクトがあった場合に、下記のようなitem1item2idに当たる部分だけ追加するにはどうすればいいでしょうか。

javascript

1 2const item3 = { 3 fruits: { 4 id: 21, 5 status :"B", 6 apple: { 7 id: 13, 8 color: "red" 9 }, 10 banana: { 11 id: 12, 12 color: "yellow" 13 }, 14 strawberry: { 15 id: 17, 16 color: "red" 17 } 18 } 19};

Object.assign()を使ってみたのですがid以外の箇所も変わってしまうので、方法がありましたら教えていただきたいです。

よろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

繰り返し処理で対応して下さい。

  1. Object.keys でキーを配列化
  2. 繰り返し処理
  3. in 演算子で item に存在して、item2 に存在しないキー値を探して代入

Re: eeengineeeeeeer さん

投稿2019/08/02 03:45

編集2019/08/02 03:46
think49

総合スコア18162

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

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

0

ベストアンサー

再帰的なマージが知りたいという知的好奇心寄りな動機で、
テストデータを適当に作って用意してきただけだと思います。
一応おまけとして下に追加しますが、現実的にはそんな用途はほぼありません。

何故ならデータが汚すぎるからです。
IDとstatusと各種フルーツの名前が一つのオブジェクトにある時点でおぞましい……

しかし我々ITエンジニアの仕事は情報処理です。
こんなぐちゃぐちゃなデータじゃバグも大量に出ますし、
コードも無駄に増えますから相当読みづらくなるでしょう。

逆に言えばデータにちゃんと指向性をもたせれば今回のような要望も99%程度の割合で抑え込めるのです。
段取り八分はITエンジニアも同様です。
Array.prototype.mapLocashなんかも駆使すればいくらでもデータは加工出来るわけですからね。

JavaScript

1const fruitList = { 2 status :"B", 3}; 4const fruits = [ 5 {name: "apple", color: "red"}, 6 {name: "banana", color: "yellow"}, 7 {name: "strawberry", color: "red"} 8]; // オブジェクトの配列は凄まじく扱い安く効率が良い 9 10// ああ、アイテム2がこれだったらどんなに楽だっただろうか…… 11const fruitListId = 21; 12const fruitIdList = { 13 apple: 13, 14 banana: 12, 15 strawberry: 17 16}; 17 18const result = { 19 ...fruitList, 20 id: fruitListId, 21 fruits: fruits.map(fruit => ({ 22 id: fruitIdList[fruit.name], 23 ...fruit, 24 })) 25} 26console.log(JSON.stringify(result, null, 2));

結果

JSON

1{ 2 "status": "B", 3 "id": 21, 4 "fruits": [ 5 { 6 "id": 13, 7 "name": "apple", 8 "color": "red" 9 }, 10 { 11 "id": 12, 12 "name": "banana", 13 "color": "yellow" 14 }, 15 { 16 "id": 17, 17 "name": "strawberry", 18 "color": "red" 19 } 20 ] 21}

それでも初期でもらえるデータ型がitemとitem2しかないという前提ならば
頑張って上記のデータになるように加工するのが最も楽です。

JavaScript

1const item = { 2 fruits: { 3 status :"B", 4 apple: { 5 color: "red" 6 }, 7 banana: { 8 color: "yellow" 9 }, 10 strawberry: { 11 color: "red" 12 } 13 } 14}; 15const item2 = { 16 fruits: { 17 id: 21, 18 status :"C", 19 apple: { 20 id: 13, 21 color: "blue" 22 }, 23 banana: { 24 id: 12, 25 color: "green" 26 }, 27 strawberry: { 28 id: 17, 29 color: "red" 30 } 31 } 32}; 33const itemColumns = ["id", "status"]; 34 35const fruitsList = Object.fromEntries( 36 Object 37 .entries(item.fruits) 38 .filter(([key]) => itemColumns.includes(key)) 39); 40// {status: "B"} 41 42const fruites = Object.entries(item.fruits) 43 .filter(([key]) => !itemColumns.includes(key)) 44 .map(([key, values]) => ({_name: key, ...values})); 45// [ 46// { 47// "_name": "apple", 48// "color": "red" 49// }, 50// { 51// "_name": "banana", 52// "color": "yellow" 53// }, 54// { 55// "_name": "strawberry", 56// "color": "red" 57// } 58// ] 59 60const fruitIds = Object.fromEntries( 61 Object.entries(item2.fruits) 62 .filter(([key]) => !itemColumns.includes(key)) 63 .map(([key, val]) => [key, val.id]) 64); 65// {apple: 13, banana: 12, strawberry: 17} 66 67const item3 = { 68 id: item2.fruits.id, 69 ...fruitsList, 70 ...Object.fromEntries( 71 fruites.map(fruit => [ 72 fruit._name, 73 Object.fromEntries([ 74 ['id', fruitIds[fruit._name]], 75 ...Object.entries(fruit).filter(([key]) => key != '_name') 76 ]) 77 ]) 78 ) 79} 80console.log(JSON.stringify(item3, null, 2));

JSON

1{ 2 "id": 21, 3 "status": "B", 4 "apple": { 5 "id": 13, 6 "color": "red" 7 }, 8 "banana": { 9 "id": 12, 10 "color": "yellow" 11 }, 12 "strawberry": { 13 "id": 17, 14 "color": "red" 15 } 16}

【おまけ】 機械的にマージすれば良いだけなら

Lodashのgetとsetを覚えるのが先ですかね。

Online Lodash TesterというサイトでLodashの動作を確認出来ます

JavaScript

1result = _.set({}, 'a.b.c', 123); 2// {"a": {"b": {"c": 123}}}

JavaScriptは全ての型でプロパティにアクセス出来ますが、
nullundefinedのみプロパティを所持することもアクセスを試みることも不可能でエラーになってしまいます。
なのでキーをネストさせる場合はいちいちobj.a = {}; obj.a.b = {}; obj.a.b.c = 123;みたいに書かなければならないのですが、
Lodashのsetはその辺に対応しているわけですね。

後は再帰的に掘ってキーを見つける関数を用意するだけです。

JavaScript

1const isObject = (obj, key) => { 2 if (_.isArray(obj[key])) return false; 3 if (_.isObject(obj[key])) return true; 4 return false; 5} 6const recursiveKeys = obj => [ 7 ...Object.keys(obj).filter(key => !isObject(obj, key)), 8 ..._.flatten( 9 Object.keys(obj) 10 .filter(key => isObject(obj, key)) 11 .map(key => recursiveKeys(obj[key]).map(it => `${key}.${it}`)) 12 ) 13] 14const item = { 15 fruits: { 16 status :"B", 17 apple: { 18 color: "red" 19 }, 20 banana: { 21 color: "yellow" 22 }, 23 strawberry: { 24 color: "red" 25 } 26 } 27}; 28result = recursiveKeys(item);

JSON

1[ 2 "fruits.status", 3 "fruits.apple.color", 4 "fruits.banana.color", 5 "fruits.strawberry.color" 6]

同じようにitem2を調査したらご覧のような結果に

JSON

1[ 2 "fruits.id", 3 "fruits.status", 4 "fruits.apple.id", 5 "fruits.apple.color", 6 "fruits.banana.id", 7 "fruits.banana.color", 8 "fruits.strawberry.id", 9 "fruits.strawberry.color" 10]

後は空のオブジェクト作って、
for文かなんかでitem2itemの順番で_.setを使って適用していくだけで完成します。
ただまぁ、オブジェクト判定の辺りが私の作った関数は手抜きして作ったレベルなので、
商用利用するレベルになると全然足りません。

Date型のインスタンスとか混じると空中分解すると思います。
なので全くおすすめしませんし、保証も出来ません。

従って所詮おまけレベルと考えて、再帰的なマージよりはきっちりデータ型を取り決めて
綺麗なデータでやり取りするべきでしょう。

投稿2019/08/02 06:37

miyabi-sun

総合スコア21158

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問