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

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

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

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

Q&A

解決済

1回答

1055閲覧

javascriptの連想配列から指定のものを検索して上書きする方法

nutti

総合スコア7

JavaScript

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

0グッド

1クリップ

投稿2022/01/05 10:59

編集2022/01/05 14:09

javascriptの連想配列から指定のものを検索して上書きする方法

題名にあるのですが、連想配列の中から値を検索して、上書き(置き換える)というものなのですが、
現在の私のやり方ですととても作業が多く(エラーなども探りにくい)、使い回しも難しいので、質問させていただきました。
値を変更するのではなく、上書きしてしまいたいというのがあり、悩んでおります。
良い方法がありましたらご教授いただけたら幸いです。

下記のような連想配列があります。

var array = [ { id: "lists", value: [ [ { id: "no", value: 100, }, { id: "item", value: [ { id: "idA", value: "val A", }, { id: "idB", value: "val B", }, { id: "idC", value: [ { id: "nestID_C1", value: "val C1", }, { id: "nestID_C2", value: [ { id: "nestID_C2-1", value: "val nest c2-1" } ], }, ], }, { id: "idD", value: [ { id: "nestID_D1", value: "nest d-1", }, { id: "nestID_D2", value: [ [ { id: "nestID_D2-NO", value: "300" }, { id: "nestID_D2-1", value: "value nested d2 no-300 - 1" } ], [ { id: "nestID_D2-NO", value: "400" }, { id: "nestID_D2-1", value: "value nested d2 no-400 - 1" } ], ], }, ], }, ] } ], [ { id: "no", value: 200, }, { id: "item", value: [ { id: "idA", value: "val A", }, { id: "idB", value: "val B, }, { id: "idC", value: [ { id: "nestID_C1", value: "val nest c1", }, { id: "nestID_C2", value: [ { id: "nestID_C2-1", value: "val nested c2-1" } ], }, ], }, { id: "idD", value: [ { id: "nestID_D1", value: "nest d-1, }, { id: "nestID_D2", value: [ [ { id: "nestID_D2-NO", value: "300" }, { id: "nestID_D2-1", value: "value nested d2 no-300 - 1" } ], [ { id: "nestID_D2-NO", value: "400" }, { id: "nestID_D2-1", value: "value nested d2 no-400 - 1" } ], ], }, ], }, ] } ], ] } ];

この配列で、それぞれを置き換えたいです。
現在の私のやり方ですと、

// lists({id:"no", value: 200})/item/idC/nestID_C2/nestID_C2-1 // lists直下のNOは、状況に合わせてこちらで選択する。 // 上で記載した通り、今回は、lists下は200を取得する var oldArray = getArray(); // arrayの配列を取得 var lists = oldArray.find(el => el.id == "lists"); var itemIndex = -1; var targetNo = 200; // no200を探す for (let i=0; i<lists.value.length; i++) { const _item = lists.value[i].find(el => el.id == "no"); if (_item.value == targetNo) { itemIndex = i; break; } } // 存在しないときは終了 if (itemIndex == -1) { return; } // no 200の配列を取得 var list = lists.value[itemIndex]; // itemを取得 var item = list.find(el => el.id == "item"); // itemのvalueの中から、変更したいものを取り出す => 例:nestID_C2 -> nestID_C2-1のvalueを書き換える var idC = item.value.find(el => el.id == "idC"); var nestIDC2 = idC.value.find(el => el.id == "nestID_C2"); var nestIDC2_1 = nestIDC2.value.find(el => el.id == "nestID_C2-1"); // 書き換え nestIDC2_1.value = "new value"; // arrayの上書き処理 setArray(oldArray);
// no100の中にある、valueが400のnestID_D2-1を上書きしたい // lists({id:"no", value: 100})/item/idD/nestID_D2({id:"nestID_D2-NO", value: 400})/nestID_D2-1 // lists直下のNOと、nestID_D2下のNOは、状況に合わせてこちらで選択する。 // 上で記載した通り、今回は、lists下は100, nestID_D2下は400を取得する var oldArray = getArray(); // arrayの配列を取得 var lists = oldArray.find(el => el.id == "lists"); var itemIndex = -1; var targetNo = 100; // lists直下のno100を探す for (let i=0; i<lists.value.length; i++) { const _item = lists.value[i].find(el => el.id == "no"); if (_item.value == targetNo) { itemIndex = i; break; } } // 存在しないときは終了 if (itemIndex == -1) { return; } // no 100の配列を取得 var list = lists.value[itemIndex]; // itemを取得 var item = list.find(el => el.id == "item"); // itemのvalueの中から、変更したいものを取り出す var idD = item.value.find(el => el.id == "idD"); var nestIDC2 = idD.value.find(el => el.id == "nestID_D2"); // no400を探す var nestedTargetID = 400; var nestedItemIndex = -1; for (let i=0; i<nestIDC2.value.length; i++) { const _item = nestIDC2.value[i].find(el => el.id == "nestID_D2-NO"); if (_item.value == nestedTargetID) { nestedItemIndex = i; break; } } // 存在しないときは終了 if (nestedItemIndex == -1) { return; } var nestID_D2_1 = nestIDC2.value.find(el => el.id == "nestID_D2-1"); // 書き換え nestID_D2_1.value = "new value"; // arrayの上書き処理 setArray(oldArray);

getArraysetArrayの先はAPIになっており、そのままarrayを取得・上書きしてくれます。

上の例ですと、
idCnestIDなど階層が深いものもあり、その都度バラバラなので違うケースのときにうまく対応できずそれぞれのケースを用意しているのが現状です。

技術不足ですいませんが、何卒よろしくお願い致します。

追加1

ご質問にありましたルールについて追記いたします。
基本的には、

{ id: xxxx, value: yyyy, }

が絶対の形となっており、これが1つのまとまりとなります。
これが、同じ階層に並ぶ場合には

{ id: xxxx, value: yyyy, }, { id: aaaaa, value: bbbb, }

と同階層に連なります。

ネストされる場合には必ず

{ id: xxxx, value: [ { id: aaaaa, value: bbbbb, }, ] }

のように、親のvalueの中に新たな要素ができます。
valueは配列を持つことができ、繰り返しネストすることができます。

{ id: xxxx, value: [ [ { id: aaaaa, value: bbbbb, }, { id: ccc, value: ddd, }, ], [ ....同様 ] ] }

と繰り返すことができます。

取得したい要素のidは、

lists(x)/item/idC/nestIDC1 x = { id: target_name, value: target_value }

のような形で情報を得ることはできます。
そのため、取得したいxが含まれている

listsの直下のidがx.id, valueがx.valueのが含まれる要素

などは、状況に応じて取得する工程は必要になります。

追記2

参考例を追加いたしました。
追加内容としましては、同一階層にあるものが1階層目にしかなく誤解がありそうでしたので参考配列を変更し、例を追加いたしました。

追記3

選択要素のxの仕様にもれがあったので、追記いたしました。

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

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

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

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

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

ku__ra__ge

2022/01/05 11:58

> idCやnestIDなど階層が深いものもあり、その都度バラバラなので違うケースのときにうまく対応できず 渡されるデータの構造がバラバラなら共通化のしようがないと思いますが……。 なにかしらのルールがあるならそれを明示してください。
nutti

2022/01/05 12:30

ku__ra__ga様 コメントありがとうございます。 現状のルールを追加いたしました。 不足ありましたらまた追加いたしますのでよろしくお願い致します。
babu_babu_baboo

2022/01/05 13:37

例題には、value が [[...]] となってる箇所があるのだけれど
nutti

2022/01/05 14:14

babu_babu_baboo様 コメントありがとうございます。 一部追記いたしました。 ネストされた、valueの中身に関しましては、 value: [ [ {id:AAA, value:BBB}, {id:CCC, value:DDD} ], ......繰り返し] という構造はありえます。
babu_babu_baboo

2022/01/05 15:11

変数 array においてダブルクオーテーションで閉じていない部分が2か所あります。 lists(x)/item/idC/nestIDC1 ではなく lists(x)/item/idC/nestID_C1 ですよね? ころころ変わるから・・・。
guest

回答1

0

ベストアンサー

設定条件が面倒。
誰かが簡潔に書くのだろうけど。

js

1var array = [ 2 { 3 id: "lists", 4 value: [ 5 [ 6 { 7 id: "no", 8 value: 100, 9 }, 10 { 11 id: "item", 12 value: [ 13 { 14 id: "idA", 15 value: "val A", 16 }, 17 { 18 id: "idB", 19 value: "val B", 20 }, 21 { 22 id: "idC", 23 value: [ 24 { 25 id: "nestID_C1", 26 value: "val C1", 27 }, 28 { 29 id: "nestID_C2", 30 value: [ 31 { 32 id: "nestID_C2-1", 33 value: "val nest c2-1" 34 } 35 ], 36 }, 37 ], 38 }, 39 { 40 id: "idD", 41 value: [ 42 { 43 id: "nestID_D1", 44 value: "nest d-1", 45 }, 46 { 47 id: "nestID_D2", 48 value: [ 49 [ 50 { 51 id: "nestID_D2-NO", 52 value: "300" 53 }, 54 { 55 id: "nestID_D2-1", 56 value: "value nested d2 no-300 - 1" 57 } 58 ], 59 [ 60 { 61 id: "nestID_D2-NO", 62 value: "400" 63 }, 64 { 65 id: "nestID_D2-1", 66 value: "value nested d2 no-400 - 1" 67 } 68 ], 69 ], 70 }, 71 ], 72 }, 73 ] 74 } 75 ], 76 [ 77 { 78 id: "no", 79 value: 200, 80 }, 81 { 82 id: "item", 83 value: [ 84 { 85 id: "idA", 86 value: "val A", 87 }, 88 { 89 id: "idB", 90 value: "val B", 91 }, 92 { 93 id: "idC", 94 value: [ 95 { 96 id: "nestID_C1", 97 value: "val nest c1", 98 }, 99 { 100 id: "nestID_C2", 101 value: [ 102 { 103 id: "nestID_C2-1", 104 value: "val nested c2-1" 105 } 106 ], 107 }, 108 ], 109 }, 110 { 111 id: "idD", 112 value: [ 113 { 114 id: "nestID_D1", 115 value: "nest d-1", 116 }, 117 { 118 id: "nestID_D2", 119 value: [ 120 [ 121 { 122 id: "nestID_D2-NO", 123 value: "300" 124 }, 125 { 126 id: "nestID_D2-1", 127 value: "value nested d2 no-300 - 1" 128 } 129 ], 130 [ 131 { 132 id: "nestID_D2-NO", 133 value: "400" 134 }, 135 { 136 id: "nestID_D2-1", 137 value: "value nested d2 no-400 - 1" 138 } 139 ], 140 ], 141 }, 142 ], 143 }, 144 ] 145 } 146 ], 147 ] 148 } 149]; 150 151 152 153 154function F (a, n, r = [ ]) { 155 for (let _a of a) { 156 if (Array.isArray (_a)) 157 r = F (_a, n, r); 158 else { 159 let {id, value} = _a; 160 if (n === value) 161 r.push (a); 162 else if (Array.isArray (value)) 163 r = F (value, n, r); 164 } 165 } 166 return r; 167} 168 169 170function R (ary, path, val) { 171 172 function _R (a, path) { 173 if (Array.isArray (a)) 174 a.forEach (b=> _R (b, path)) 175 else { 176 let [t, ..._path] = path; 177 if (t === a.id) { 178 if (_path.length) 179 _R (a.value, _path); 180 else 181 a.value = val; 182 } 183 } 184 } 185 186 _R (ary, path.split ('/')); 187} 188 189//_______________ 190 191 192R (F (array, 200), 'item/idC/nestID_C1', 'new value'); 193console.log (array); 194 195

投稿2022/01/05 15:23

babu_babu_baboo

総合スコア616

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

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

nutti

2022/01/07 00:35

ご回答いただき、ありがとうございます。 お返答にお時間かかってしまってすいません。 全く思いもつかない方法でとても勉強になります。 2点質問なのですが、 ① let [t, ..._path] = path; という記述の部分がわからず、調べてみたのですがわからなかったので教えていただけますと幸いです。 ② こういった書き方の勉強?などはなにかおすすめの分野?というのでしょうか?があったりしますでしょうか? 関数内で、自分の関数を呼び出すなど行なったことがなく、、、 全く思いもつかない方法でしたので、もっと深めたいと思いました。 無知ですいませんが、なにかアドバイスいただけたら幸いです。 何卒よろしくお願い致します。
babu_babu_baboo

2022/01/07 11:03 編集

1. 以下のように代入されます(分割代入) let [a, ...b] = [0,1,2,3,4]; a => 0; b => [1,2,3,4] 2.「自分自身を呼び出す」再帰処理です ?.「おすすめの分野」、究極のショートコーディングを目指す! 今回のグローバル変数の書き換えは、ミスを誘発しやすいので好きではありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問