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

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

ただいまの
回答率

90.84%

  • JavaScript

    14828questions

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

javascriptの配列代入の表記方法

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 389

kobac

score 1

 質問内容

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

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

 該当のソースコード

//ID,名前
var arrUser =[
  ['001', '小林'],
  ['002', '山田'],
  ['003', '中村'],
  ['001', '大林']
];

//IDが重複しているレコードを削除
var arrNewUser = [];
for (var i = 0; i < arrUser.length; i++) {
  arrNewUser[arrUser[i][0]] = arrUser[i]; // この表記法がわからない
}
console.table(arrNewUser); //山田,中村,大林

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+4

 利用用途

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

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

 問題点

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

function original (arrUser) {
  var arrNewUser = [];

  for (var i = 0; i < arrUser.length; i++) {
    arrNewUser[arrUser[i][0]] = arrUser[i];
  }

  return arrNewUser;
}

console.table(original([['001', '小林'],['002', '山田'],['003', '中村'],['001', '大林']]));
console.dir(original([['__proto__','伊藤']]));
console.dir(original([['length','佐々木']]));  // RangeError: Invalid array length

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

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

 Map

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

function fixed (users) {
  return new Map(users);
}

var userMap = fixed([['001', '小林'],['002', '山田'],['003', '中村'],['001', '大林'],['__proto__','伊藤'],['length','佐々木']]);

console.log(JSON.stringify([...userMap.entries()]));  // [["001","大林"],["002","山田"],["003","中村"],["__proto__","伊藤"],["length","佐々木"]]

参考情報。

Re: kobacj さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/27 08:55

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

    キャンセル

  • 2018/04/27 12:16

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

    キャンセル

+3

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

var arrNewUser = {};

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/27 12:06

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

    キャンセル

+3

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

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

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/27 12:13

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

    キャンセル

checkベストアンサー

+2

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/27 09:42

    このような表記法はあるのでしょうか?

    キャンセル

  • 2018/04/27 10:10

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

    キャンセル

  • 2018/04/27 12:04

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

    キャンセル

  • 2018/04/27 13:43

    To: nucha さん
    > '001'は文字列なので、配列のインデックスとして使うのは問題です。
    はい、文字列として扱われます。
    arrNewUser['001'] = arrUser[0];

    > [ 1:['001', '大林'], 2:['002', '山田'], 3:['003', '中村'] ]
    SyntaxErrorになりそうですが、本当に問題ないのでしょうか。

    キャンセル

  • 2018/04/27 13:52 編集

    表記とありますので、
    動いてるシステムとして
    arrNewUser[arrUser[i][0]] = arrUser[i];
    の行(配列の内部に配列が入る表記法に混乱)の解説のみに終止しました。

    質問の真意に対しては解答になっていると思ってのことです。
    質問の内容としては、001のデータが問題なのではなく、

    arrNewUse[] のインデックス部分に arrUser[i][0] がはいってるのが理解できないんだけど問題ないんですか?

    という解釈をしました。
    なので、問題ないという解答をしています。

    質問の編集済みのコードがエラーを出すことに対して別問題とかってに判断したことはごめんなさい。

    幸いにも質問者さんへは納得いただいたようで「実際のコードでは元の配列を作成する際にIDを文字列から数値に変換」ともありますし、質問の文章編集が原因のエラーのことを先に問題視してしまうと、本来の質問内容が曖昧になってしまい逆に理解がしにくかったこととおもいます。

    なにはともあれ、ご迷惑おかけしてもうしわけありません。

    ちゃんと通じてベストアンサーもらってもマイナス評価2つもくらうとは・・・痛恨です。

    キャンセル

  • 2018/04/27 21:26

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

    キャンセル

  • 2018/04/27 21:42 編集

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

    キャンセル

  • 2018/04/28 10:55

    回答を評価するのは質問者ではなく、「質問者が満足するか」で決定するものでもない、ということです。
    そもそも、質問者の評価ならベストアンサーで完結しますので、評価システム自体が不要ですよね。
    https://teratail.com/help#aboutReplyVote

    ---
    間違いの内容は2018/04/27 13:43のコメントで全てですが、私は記法よりもプロパティを文字列として扱う性質を理解していない回答になっている事が気になりますね(この部分は、HayatoKamonoさんがとても丁寧に回答して下さっています)。
    この回答を見た人がこの回答者と同じように「動いているというのであれば、001が数字として自動で型変換されてる」と誤解してしまう可能性があります。
    質問者はたまたまNumber型に変換していたので、この回答がマッチしていましたが、後から見る人もたまたまNumber型に変換して代入するとは限りません。

    キャンセル

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

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    14828questions

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