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

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

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

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

5回答

5864閲覧

【js】配列の内容で処理を分岐させたい

MikiSF

総合スコア12

JavaScript

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2018/08/18 13:54

5つの文字列を入れた配列があり、その並び順ごとに処理を分岐させたいのですがうまくいきません。
おそらく基本的な何かを理解していないのだと思いますが、ご教授いただけますと幸いです。

javascript

1switch( Array ) { 2 case ["F","F","T","T","T"]: 3 console.log('Aの処理'); 4 break; 5 6 7 case ["F","T","T","T","T"]: 8 console.log('Bの処理'); 9 break; 10 11 }

上記でやりたいことが伝わるでしょうか。
FFFFFならAの処理、
TFFFFならBの処理、
TTFFFならCの処理…と、すべての組み合わせで処理を変えたいのです。

Arrayに5つの文字列を入れるところまではできているのですが…。
よろしくお願いいたします。

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

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

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

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

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

guest

回答5

0

ベストアンサー

こんにちは。

おそらく基本的な何かを理解していないのだと思いますが、

とおっしゃっている、"基本的な何か" とは以下の2点かと思われます。

 (1) javascript の switch文で、 switch(x ) で与える x と各 case y :y とは同値演算子 ===で比較されること。(つまり x === y が true になる case y : が選ばれる。)

(2) 二つのArrayオブジェクト ab があり、両者が過不足なく同じ要素を同じ順番で含んでいても、ab が別個のオブジェクトであれば、 a === bfalse になること

上記の(1) については、以下に記載があります。

ECMAScript® Language Specification: 12.11 The switch Statement

If input is equal to clauseSelector as defined by the === operator, then …

(2) については、以下のようにして確かめられます。

shell

1$ node -v 2v10.8.0 3$ node 4> var a = ["T","F","T","F","T"] 5undefined 6> var b = ["T","F","T","F","T"] 7undefined 8> a === b 9false 10>

 
2つの配列abが、同じ要素を同じ順番で過不足なく持っている、すなわち「ab 内容が同じ配列である」という判定を、どのようなコードで書けばよいか? という問題は、以下の投稿

からも分かるように、様々な案が出てくるテーマでもあります。
ですが、上記のstackoverflowの質問への回答で、一番得票数が多い Array.prototype.equalsを自作するという案だと、MikiSFさんのご質問にあるswitch 〜 case を使うことができません。

MikiSFさんのご質問の解法として、あくまでswitch 〜 caseを使うことにするならば、対象とする配列の要素を結合した文字列をswitchの対象にするのが分かり易い方法かなと思います。つまり、["F","F","T","T","T"] であれば、"FFTTT" をswitchの対象とします。以下はコード例です。

javascript

1const sampleAry = ["F","F","T","T","T"]; 2 3switch (sampleAry.join('')) { 4 case 'FFTTT': 5 console.log('Aの処理'); 6 break; 7 case 'FTTTT': 8 console.log('Bの処理'); 9 break; 10 default: 11 console.log('その他の処理'); 12 break; 13}

上記を実行すると、Aの処理と表示されます。

以上参考になれば幸いです。


追記

配列要素の "T" を"1"、"F"を"0"と置き換え、要素を結合した文字列を作ると、例えば["T","F","T","F","T"] は "10101" となり、さらに"10101" を2進数と考えれば、 10進数としては 21 です。このように "T"か "F" を持つ配列を対応する10進数に変換した値で switch させる手もあるかと思いました。

具体的なコードとしては、少しトリッキーかもしれませんが、例えば以下のように、Array.prototype.valueOfメソッドをオーバーライドし対応する10進数を返すようにしておくと、配列の変数sampleAry があったときに、+を変数の前に置いて +sampleAry とするとvalueOfが呼ばれて10進数に変換されます。

javascript

1Array.prototype.valueOf = function() { 2 return parseInt(this.map(e => e === 'T' ? '1':'0').join(''), 2); 3}; 4 5const sampleAry = ["T","F","T","F","T"]; // 2進数の10101を表すものと考えれば、10進数だと21 6 7switch(+sampleAry) { 8 case 0: 9 console.log('["F","F","F","F","F"] の場合の処理'); 10 break; 11 case 1: 12 console.log('["F","F","F","F","T"] の場合の処理'); 13 break; 14 case 2: 15 console.log('["F","F","F","T","F"] の場合の処理'); 16 break; 17 // ・・・ 18 case 21: 19 console.log('["T","F","T","F","T"] の場合の処理'); 20 break; 21 // ・・・ 22 case 31: 23 console.log('["T","T","T","T","T"] の場合の処理'); 24 break; 25 default: 26 break; 27}

上記を実行すると、case 21: に該当して、["T","F","T","F","T"] の場合の処理 と表示されます。(同じコードを、https://jsfiddle.net/jun68ykt/kose0cqu/19/ にも上げておきました。)


以下、蛇足です。

質問者のMikiSFさんから

switchにこだわる理由があるわけではないので、他の方法も調べてみます!

とのコメントを頂きましたので、以下を補足します。

2つの配列が同じ内容である判定関数を自作せずに、配列などの操作でよく使われるライブラリ Lodash を利用する手もあります。これの _.isEqual(value, other)を使ったコードを以下に上げておきました。

https://jsfiddle.net/jun68ykt/jqp63Lum/6/

ご参考まで。


何度もお節介すみません。

switch 〜 caseを使うにせよ、if 〜 else ifを使うにせよ、該当する処理にたどりつくのに、caseあるいはifの数に比例した時間がかかります。(計算量のオーダーが O(n) である、と言ったります。 ) 言い換えると、FFFFFからTTTTTまですべてのケースは2の5乗で32個あり、これらのそれぞれに case または if があるとすると、最悪の場合は32回の比較をへて、ようやく該当する処理が決まるということがあり得ます。
これを避けたいので、私がもし業務上で、このご質問と同様の課題に遭遇したら、おそらく以下のコードをベースにするでしょう。

javascript

1const operations = { 2 FFFFF() { console.log('[F,F,F,F,F]の処理'); }, 3 FFFFT() { console.log('[F,F,F,F,T]の処理'); }, 4 /* ・・・ */ 5 TFTFT() { console.log('[T,F,T,F,T]の処理'); }, 6 /* ・・・ */ 7 TTTTT() { console.log('[T,T,T,T,T]の処理'); }, 8}; 9 10const sampleAry = ["T","F","T","F","T"]; 11 12operations[sampleAry.join('')]();  // => "[T,F,T,F,T]の処理" と出力される。

https://jsfiddle.net/jun68ykt/1bLm7eyd/14/ にも上げておきました。

これに、エラー処理などを加えたり適宜リファクタして、安全かつ最適化されたコードに仕上げていくだろうと思います。

投稿2018/08/18 14:39

編集2018/08/20 01:09
jun68ykt

総合スコア9058

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

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

MikiSF

2018/08/19 05:36

大変わかりやすく、かつ詳細に教えていただいてありがとうございました! 教えていただいた方法で一旦やってみますが、switchにこだわる理由があるわけではないので、他の方法も調べてみます!
jun68ykt

2018/08/19 07:10

> switchにこだわる理由があるわけではないので、他の方法も調べてみます! なるほどです。 switch の他にどういう書き方が良いか、また迷ったら、再度ご質問されるとよいでしょう。
jun68ykt

2018/08/19 07:58 編集

オマケというか蛇足ですが、Lodash のisEqualを使うコードを回答に追記しました。「ふーん。そんなのがあるんだ」程度に眺めてもらえればと思います。
MikiSF

2018/08/19 09:24

ありがとうございます! こちらも詳しく見てみます。
jun68ykt

2018/08/19 10:04 編集

ご返信ありがとうございます。回答にもうひとつお節介を追加させて頂きました。自分が仕事上で書くならこのコードをベースにブラッシュアップしていくだろうというものです。
MikiSF

2018/08/20 02:08

なるほどです…。 確かに、動作を実現するのに精一杯で、軽くしていく、安全にしていく、というところまでなかなか至れていないです…。 丁寧にアドバイス頂き本当に助かります。 ありがとうございます!
think49

2018/08/20 03:29

> 最悪の場合は32回の比較をへて、ようやく該当する処理が決まるということがあり得ます。 Array#join() も32回分の演算コストがかかるので、配列を廃止して、String型の値 'TFTFT' でデータを持っておく方法も…。 あるいは、フラグがNパターン -> N進数(2bitならビット演算がおそらく、最速) 配列の利点は、1文字では足りず、可変長データを収められる性質にあります。
jun68ykt

2018/08/25 14:52 編集

※ ここに書いた当方のコメントを消去させて頂きました。お見苦しい点、誠に申し訳ありません。
think49

2018/08/21 03:29

一応、実装例は回答で触れたリンク先にあります。 https://teratail.com/questions/84834 > Array.prototype.valueOf 今更ですが、今気が付いたので一言。 フラグ管理の為だけに、全体に影響するビルトインオブジェクトを拡張するのはお勧めしません。 予め、プリミティブ化しやすいように準備するならば、CustomArrayをコンストラクタ定義しておき、そちらで自由に拡張させる方が安全かと。
jun68ykt

2018/08/25 14:52 編集

※ ここに書いた当方のコメントを消去させて頂きました。重ね重ね、お見苦しい点、誠に申し訳ありません。
think49

2018/08/24 12:11

副題でもコードが適用される事はあります。 そしてそれが初心者であった場合、「未知の」エラーを誘発させるリスクがあります。 「既知の」リスクにする為に、私は指摘しました。 jun68yktさん自身は勿論、よくご存知と思いますが、質問者は違うと思います。
think49

2018/08/24 12:14

> 質問の本題から外れるコードを余分に加えて肥大化させることは、 私としては、「リスク説明なし」が懸念で、コードを追記してもらう意図はありませんでした。 代案を示したのは、「否定だけでは前向きではない」という考えからで、代案はあくまで個人的な見解です。
guest

0

2つの配列を受け取ってその内容が一致しているかを判定する関数があれば、「5つの文字列を入れた配列の並び順」ごとに処理を分岐させることができます。
それさえ出来れば、あとは各パターンごとに処理を書いていくだけです。

「2つの配列を受け取ってその内容が一致しているかを判定する関数」は自前で作ってしまいましょう。

javascript

1var hoge = ["F","F","T","T","T"]; // 5つの文字列を入れた配列 2 3// 各パターンごとに処理 4if (isEqualArray(hoge, ["F","F","T","T","T"])) { 5 console.log('Aの処理'); 6} else if (isEqualArray(hoge, ["F","T","T","T","T"])) { 7 console.log('Bの処理'); 8} else { 9 console.log('AでもBでもない処理'); 10} 11 12// 2つの配列を受け取ってその内容が一致しているかを判定する関数 13function isEqualArray(array1, array2) { 14 if (array1.length != array2.length) { return false; } 15 16 for (var i=0; i<array1.length; i++) { 17 if (array1[i] != array2[i]) { return false; } 18 } 19 20 return true; 21}

投稿2018/08/18 14:19

編集2018/08/18 14:21
ku__ra__ge

総合スコア4524

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

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

MikiSF

2018/08/19 05:37

ありがとうございます! シンプルでわかりやすかったです! 参考にさせていただきます!
guest

0

Reference型

オブジェクトはReference型なので、

JavaScript

1console.log(["F","F","T","T","T"] === ["F","F","T","T","T"]); // false

JSON.stringify()

配列の要素値がPrimitive型なら、

JavaScript

1'use strcit'; 2function sample (array) { 3 switch (JSON.stringify(array)) { 4 case '["F","F","T","T","T"]': 5 console.log('処理A'); 6 break; 7 case '["F","T","T","T","T"]': 8 console.log('処理B'); 9 break; 10 } 11} 12 13sample(["F","F","T","T","T"]); 14sample(["F","T","T","T","T"]);

フラグ管理

Re: MikiSF さん

投稿2018/08/19 01:56

編集2018/08/19 06:07
think49

総合スコア18162

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

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

MikiSF

2018/08/19 05:32

ありがとうございます! ちょっと私には難しいですががんばって勉強します!
guest

0

配列がフラグ管理で T と F が true , false なら、ビット演算を学習すると良さげです。

投稿2018/08/19 01:55

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

MikiSF

2018/08/19 05:33

そうなのですね! 調べてみます! ありがとうございます!
guest

0

配列は使えません。
配列の要素を全部つないで、5文字の文字列にしましょう。

投稿2018/08/18 14:20

iruyas

総合スコア1067

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

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

MikiSF

2018/08/19 05:36

ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問