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

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

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

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

Q&A

解決済

3回答

975閲覧

Javascriptでの多次元配列を用いたデータ作成とpush

Kryptografin

総合スコア1

JavaScript

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

2グッド

2クリップ

投稿2022/11/01 20:07

編集2022/11/01 20:13

前提

質問失礼いたします。
はじめての質問ですので至らないところがあると思いますが、宜しくお願い致します。

Javascriptで多次元リストを用いてあるデータを作ろうとしたところ、思いがけない所で躓いてしました。。。

実現したいこと

Javascript

1 2// 以下の2つの配列を基にして 3 4// 1. url名とtitle名をペアに持つ二次元配列 (ペア数は可変) (例 5let toSaveUrlsTitles = [ 6 ["url1", "title1"], 7 ["url2", "title2"] 8] 9// 2. すでにある何個かのデータの配列 (こちらの要素数は固定) (例 10let DataValue = ["value1", "value2"]; 11 12 13 14// urlと固定の文字列("key_")を組み合わせたキーを持つ、以下のようなオブジェクトを作りたい。 15 16// {"key_(url名)" : [(すでにある値...), "(title名)"] } (例 17NewData = { 18 "key_url1": ["value1", "value2", "title1"], 19 "key_url2": ["value1", "value2", "title2"] 20} 21

方針

for文等でurl名とtitle名のペアの二次元配列を回し、

Javascript

1{ "key_url1": ["value1", "value2"] }

というようなオブジェクトを一度作った後、
title名をpushするという方針を取りました。

得られた結果

しかし結果は

Javascript

1{ 2"key_url1": ["value1", "value2", "title1", "title2"], 3"key_url2": ["value1", "value2", "title1", "title2"] 4}

というように、titleが二つとなってしましました。
(予想されていた結果は一つのみ。"key_url1"の時は"title1"のみ、"key_url2"の時は"title2"のみ)

ソースコード

for of 文、for文、for Each文を試しましたがどれも同じような結果になりました。

共通データ

Javascript

1 2let NewData = {}; 3 4let toSaveUrlsTitles = [ 5 ["url1", "title1"], 6 ["url2", "title2"] 7] 8 9let DataValue = ["value1", "value2"]

for of

Javascript

1for (let i of toSaveUrlsTitles) { 2 let BaseKey = "key_"; 3 let WholeKey = ""; //"key_url1" 4 5 WholeKey = BaseKey; 6 WholeKey += i[0]; 7 8 NewData[WholeKey] = DataValue; 9 NewData[WholeKey].push(i[1]); 10} 11console.log(NewData); 12

for

Javascript

1for(let i=0; i<toSaveUrlsTitles.length; i++){ 2 let CurrentArr=toSaveUrlsTitles[i]; // 多重配列を分解したもの 3 4 let BaseKey = "key_"; 5 let WholeKey = ""; 6 7 WholeKey = BaseKey; 8 WholeKey += CurrentArr[0]; 9 10 NewData[WholeKey] = DataValue; 11 NewData[WholeKey].push(CurrentArr[1]); 12} 13console.log(NewData);

for Each

Javascript

1 2toSaveUrlsTitles.forEach(function (v) { 3 let BaseKey = "key_"; 4 let WholeKey = ""; 5 6 WholeKey = BaseKey; 7 WholeKey += v[0]; 8 9 NewData[WholeKey] = DataValue; 10 NewData[WholeKey].push(v[1]); 11}) 12console.log(NewData);

その他試したこと

途中途中にconsole.log()を挟み、
for ofで言えば

Javascript

1 console.log(i[1]);

として、.push()されるはずのものを確認しました。
そしてそこではちゃんと

Javascript

1"title1"

と出ていました。

補足情報(FW/ツールのバージョンなど)

chrome, firefoxで検証済み

はじめてですのでわかりにくい部分が多々あると思いますが、よろしくお願いいたします。

Cocode, gandam👏を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

完成コード例

以下のコードでご希望の処理が可能です。

javascript

1const NewData = {}; 2const toSaveUrlsTitles = [ 3 ["url1", "title1"], 4 ["url2", "title2"] 5]; 6const DataValue = ["value1", "value2"]; 7 8 9for (const arr of toSaveUrlsTitles) { 10 const key = `key_${arr[0]}`; 11 const val = [...DataValue, arr[1]]; 12 13 NewData[key] = val; 14} 15 16console.log(NewData);

不具合の原因

質問者様手法だと配列の 「参照コピー」 になっているからです。

参照コピーとは

配列をコピーする際に新しい変数の中に、元の配列の変数名を書いてしまうと、2つの配列がリンクされた状態になっています。

javascript

1// 参照コピー 2const original = [1, 2, 3]; 3const refCopy = original; 4refCopy.push(4); 5 6console.log(original); // [1, 2, 3, 4] 7console.log(refCopy); // [1, 2, 3, 4]

ですので、質問者様のコードはDataValueの値を利用しているだけのつもりが、実際にはDataValueそのものを編集してしまっている状態です。

独立したコピーの作成方法

2つの配列をリンクさせたくない場合、元の配列の変数名をそのまま書くのではなく、 「スプレッド構文」 という配列を一旦バラバラにばらしてやる方法で、新規の配列を作成しましょう。

javascript

1// 独立したコピー 2const original2 = [1, 2, 3]; 3const newCopy = [...original2]; // スプレッド構文 4newCopy.push(4); 5 6console.log(original2); // [1, 2, 3] 7console.log(newCopy); // [1, 2, 3, 4]

質問者様のコード修正版

スプレッド構文で新しい配列を作れば、質問者様のコードでも意図通りの処理が行われます。

javascript

1const NewData = {}; 2const toSaveUrlsTitles = [ 3 ["url1", "title1"], 4 ["url2", "title2"] 5]; 6const DataValue = ["value1", "value2"]; 7 8for (let i of toSaveUrlsTitles) { 9 let BaseKey = "key_"; 10 let WholeKey = ""; //"key_url1" 11 12 WholeKey = BaseKey; 13 WholeKey += i[0]; 14 15 NewData[WholeKey] = [...DataValue]; // スプレッド構文 16 NewData[WholeKey].push(i[1]); 17} 18console.log(NewData);

投稿2022/11/01 21:34

編集2022/11/01 21:47
Cocode

総合スコア2314

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

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

Kryptografin

2022/11/02 02:58

とても丁寧な解説をして頂きありがとうございました。 無事解決できました。 実はCocode様の仰る参照コピーのことも少しだけ知っており、 `new Array()` などもやってみたのですが、うまくいっていませんでした。 もう一度詳しくJavascriptのコピーについて調べてみたいと思います。 とても助かりました。ありがとうございました。
guest

0

欲しい結果を考えると、2つの新しい配列(URL毎に1つ)を作る必要がありますよね。ところが、質問文のコードでは1つも配列を作っていないのです。

js

1 NewData[WholeKey] = DataValue;

このコードでは、NewData[WhokeKey]DataValue の両方から1つの配列を指すようになります。配列のコピーなどは行われていません。

ですので、ここで配列のコピーを作る必要があります。コピーする方法はいろいろあり、下記は一例です。

js

1 NewData[WholeKey] = Array.from(DataValue);

JavaScript では変数名を大文字で始めるのはかなり奇妙に見えます。人に見せるコードでは小文字で始めたほうが無難です。

投稿2022/11/01 21:19

int32_t

総合スコア20850

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

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

Kryptografin

2022/11/02 04:21

解答ありがとうございます。 配列のコピーについて、再度詳しく調べてみたいと思います。 また命名規則についてのご指摘、とても勉強になりました。 確かにJavascriptではローワーキャメルケースが大半であるように思います。 自身でもしっかり意識してコードを書くように心がけたいと思います。 解答ありがとうございました。
guest

0

javascript

1const a=[ 2 ["url1", "title1"], 3 ["url2", "title2"] 4]; 5const b=["value1", "value2"]; 6const c=Object.fromEntries(a.map(x=>([`key_${x[0]}`,b.concat(x[1])]))); 7console.log(c);

投稿2022/11/02 00:37

yambejp

総合スコア114784

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問