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

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

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

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

Q&A

解決済

4回答

1425閲覧

javascriptの配列代入の表記方法

kobac

総合スコア188

JavaScript

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

0グッド

0クリップ

投稿2018/04/26 10:42

質問内容

ユーザーの「ID」「氏名」が入った二次元配列に対して、IDが重複していたら重複を削除する(後ろに入っているレコードを残す)というプログラムがあるのですが、
表記方法が見慣れない書き方になっており、手を加えられない状態です(例によって製作者は不在)。

この表記でどういう動作をしているのか、教えていただけないでしょうか。
また、同じ様な表記方法をしているリファレンスや参考ページがあればリンクを貼っていただけると大変助かります。

該当のソースコード

javascript

1 2//ID,名前 3var arrUser =[ 4 ['001', '小林'], 5 ['002', '山田'], 6 ['003', '中村'], 7 ['001', '大林'] 8]; 9 10//IDが重複しているレコードを削除 11var arrNewUser = []; 12for (var i = 0; i < arrUser.length; i++) { 13 arrNewUser[arrUser[i][0]] = arrUser[i]; // この表記法がわからない 14} 15console.table(arrNewUser); //山田,中村,大林

恐らくIDが同じであれば上書きをしているのだと思いますが、こういう書き方はアリなんでしょうか。(当然アリだから動いているんですが・・・)

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

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

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

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

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

guest

回答4

0

利用用途

恐らくIDが同じであれば上書きをしているのだと思いますが、こういう書き方はアリなんでしょうか。(当然アリだから動いているんですが・・・)

上書きの是非は「仕様が用途にマッチするか」に尽きるので、コードだけでは判断できません。

問題点

現行仕様を強襲すると、既定のプロパティと衝突してしまう問題があります。

JavaScript

1function original (arrUser) { 2 var arrNewUser = []; 3 4 for (var i = 0; i < arrUser.length; i++) { 5 arrNewUser[arrUser[i][0]] = arrUser[i]; 6 } 7 8 return arrNewUser; 9} 10 11console.table(original([['001', '小林'],['002', '山田'],['003', '中村'],['001', '大林']])); 12console.dir(original([['__proto__','伊藤']])); 13console.dir(original([['length','佐々木']])); // RangeError: Invalid array length

配列に数値以外のプロパティで代入する事は本来の用途ではなく、プロパティ拡張には既定プロパティと衝突する危険性が常にあります。
整理すれば、次のオブジェクトまで落とし込めますが、__proto__ と衝突する問題は残っています。

JavaScript

1{"001":"大林","002":"山田","003":"中村"}

Map

この問題を解決する最も簡単な方法はMapを使用する事です。

JavaScript

1function fixed (users) { 2 return new Map(users); 3} 4 5var userMap = fixed([['001', '小林'],['002', '山田'],['003', '中村'],['001', '大林'],['__proto__','伊藤'],['length','佐々木']]); 6 7console.log(JSON.stringify([...userMap.entries()])); // [["001","大林"],["002","山田"],["003","中村"],["__proto__","伊藤"],["length","佐々木"]]

参考情報。

Re: kobacj さん

投稿2018/04/26 11:53

編集2018/04/26 13:42
think49

総合スコア18156

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

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

think49

2018/04/26 23:55

ふと、思いましたが、console.tableが分かりづらい原因の一つかもしれません。console.dirで出力する方がイメージしやすいかも。
kobac

2018/04/27 03:16

ありがとうございます。参考情報のリンク、大変助かります!
guest

0

こういう書き方はアリなんでしょうか。

以下で説明する問題があるため、ナシだと思います。

arrNewUser[arrUser[i][0]] = arrUser[i];

の部分はfor文の1ループ目では以下のように例えば置き換わります。

arrNewUser['001'] = ['001', '小林'];

なので、一旦、このコードをもっと簡易的なものに説明用にこうしてみます。

var arrNewUser = []; arrNewUser['001'] = ['001', '小林'];

では、この配列に対して、forEachなどの配列操作を行なったり、lengthプロパティーを参照したりすると、どうなるかというと、

var arrNewUser = []; arrNewUser['001'] = ['001', '小林']; console.log(arrNewUser) // [ ] - 環境によっては空の配列が表示されることもあるようです。 console.log(arrNewUser.length); //0 - lengthは0 arrNewUser.forEach(function(value, index) { console.log('hello'); // 何も表示されない console.log(value, index); // 何も表示されない }) console.log(arrNewUser['001']) // こうした場合のみ[ '001', '小林' ]と出る

https://codepen.io/anon/pen/OZRgJO

というようにおかしな挙動になってしまうので、こういう場合はObjectMapを使うべきだと思います。

let arrNewUser = {}; arrNewUser['001'] = ['001', '小林']; console.log(arrNewUser); // { '001': [ '001', '小林' ] } console.log(arrNewUser['001']); // [ '001', '小林' ] Object.keys(arrNewUser).forEach(function(key) { console.log(arrNewUser[key]); // [ '001', '小林' ] });
let arrNewUser = new Map(); arrNewUser.set('001', ['001', '小林']); console.log(arrNewUser); // Map { '001' => [ '001', '小林' ] } console.log(arrNewUser.get('001')); // [ '001', '小林' ] console.log(arrNewUser.size); // 1 for (let user of arrNewUser.values()) { console.log(user); // [ '001', '小林' ] }

投稿2018/04/26 11:26

編集2018/04/27 01:16
HayatoKamono

総合スコア2415

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

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

kobac

2018/04/27 03:13

正常に出力されない事例まで丁寧に解説いただきありがとうございます。 正しいコードも提示いただき大変助かりました。
guest

0

ちゃんとやるならarrNewUserはObjectにすべきですね

javascript

1var arrNewUser = {};

javascriptの配列はデータの投入方法によって多少ゆるく処理してくれます

javascript

1var a=[]; 2a["x"]=1; 3console.log(a); 4var b=[]; 5b[2]=1; 6console.log(b);

投稿2018/04/26 11:08

yambejp

総合スコア114572

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

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

kobac

2018/04/27 03:06

気づいていなかった点までアドバイスありがとうございます!
guest

0

ベストアンサー

arrNewUserとして新しい配列を作っていく中で重複は除外していきたいんですね。

arrNewUser[arrUser[i][0]] = arrUser[i];

一番目[001,小林] を考えてみましょう
arrUser[i][0] は? 001です
arrUser[i] は? [001,小林] です。
arrNewUser[ 001 ] = [001,小林]

この時点で
[ 1:[001,小林] ] ができます。
この調子で
[ 1:['001', '小林'], 2:['002', '山田'], 3:['003', '中村'] ]
ができるのですが。。。

次 [001,大林]でどうなるか

arrNewUser[001] = [001,大林]

arrNewUser の 1には一人目で [ 001,小林 ] が入っています。
ということで、結果的に1番目の小林を上書きしてしまい、

[ 1:['001', '大林'], 2:['002', '山田'], 3:['003', '中村'] ]
になるということです。

投稿2018/04/26 11:03

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

x_x

2018/04/27 00:42

このような表記法はあるのでしょうか?
退会済みユーザー

退会済みユーザー

2018/04/27 01:10

表記方法としては特に問題はありません。 配列のインデックスに配列の中の値を代入しただけです。 上記のようなデータ中のID番号をインデックスにしたい場合にはよく使割れると思います。 ただ、細かいことを言えば、 '001'は文字列なので、配列のインデックスとして使うのは問題です。 動作は確認していないのですが、動いているというのであれば、001が数字として自動で型変換されてるのか、arrNewUserが001(文字列)を受け取ったことでオブジェクトとして変換されてるのか。。。すいません。そこのところは確認する時間がないので省かせてもらいます。
kobac

2018/04/27 03:04

配列の内部に配列が入る表記法に混乱していましたが、元の配列のIDをインデックスに使っているだけなんですね。わかりやすい説明ありがとうございました。 IDを'001'として文字列で持っている件ですが、実際のコードでは元の配列を作成する際にIDを文字列から数値に変換していました。例示が不適切で申し訳ありません。
think49

2018/04/27 04:43

To: nucha さん > '001'は文字列なので、配列のインデックスとして使うのは問題です。 はい、文字列として扱われます。 arrNewUser['001'] = arrUser[0]; > [ 1:['001', '大林'], 2:['002', '山田'], 3:['003', '中村'] ] SyntaxErrorになりそうですが、本当に問題ないのでしょうか。
退会済みユーザー

退会済みユーザー

2018/04/27 05:04 編集

表記とありますので、 動いてるシステムとして arrNewUser[arrUser[i][0]] = arrUser[i]; の行(配列の内部に配列が入る表記法に混乱)の解説のみに終止しました。 質問の真意に対しては解答になっていると思ってのことです。 質問の内容としては、001のデータが問題なのではなく、 arrNewUse[] のインデックス部分に arrUser[i][0] がはいってるのが理解できないんだけど問題ないんですか? という解釈をしました。 なので、問題ないという解答をしています。 質問の編集済みのコードがエラーを出すことに対して別問題とかってに判断したことはごめんなさい。 幸いにも質問者さんへは納得いただいたようで「実際のコードでは元の配列を作成する際にIDを文字列から数値に変換」ともありますし、質問の文章編集が原因のエラーのことを先に問題視してしまうと、本来の質問内容が曖昧になってしまい逆に理解がしにくかったこととおもいます。 なにはともあれ、ご迷惑おかけしてもうしわけありません。 ちゃんと通じてベストアンサーもらってもマイナス評価2つもくらうとは・・・痛恨です。
think49

2018/04/27 12:26

私の知る限りでは、質問者がベストアンサーを選ぶことで、回答への評価が覆ったことはありません。 コメントでその回答への問題が提示された時に、同意した方がマイナス評価しているように見受けられる場面はあります。 回答は同じ問題に直面した人が参考にするものでもありますので、回答に間違いがあれば、マイナス評価されやすくなります。
退会済みユーザー

退会済みユーザー

2018/04/27 12:43 編集

うーん。。。つまり?? この解答スタイルはここでは受け入れられないと? では今解答中の問題が解決したら退場します。
think49

2018/04/28 01:55

回答を評価するのは質問者ではなく、「質問者が満足するか」で決定するものでもない、ということです。 そもそも、質問者の評価ならベストアンサーで完結しますので、評価システム自体が不要ですよね。 https://teratail.com/help#aboutReplyVote --- 間違いの内容は2018/04/27 13:43のコメントで全てですが、私は記法よりもプロパティを文字列として扱う性質を理解していない回答になっている事が気になりますね(この部分は、HayatoKamonoさんがとても丁寧に回答して下さっています)。 この回答を見た人がこの回答者と同じように「動いているというのであれば、001が数字として自動で型変換されてる」と誤解してしまう可能性があります。 質問者はたまたまNumber型に変換していたので、この回答がマッチしていましたが、後から見る人もたまたまNumber型に変換して代入するとは限りません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問