154

次のような非常に長い条件ステートメントがあります。

if(test.type == 'itema' || test.type == 'itemb' || test.type == 'itemc' || test.type == 'itemd'){
    // do something.
}

この式/ステートメントをより簡潔な形式にリファクタリングできるかどうか疑問に思っていました。

これを達成する方法について何か考えはありますか?

4

15 に答える 15

242

値を配列に入れ、アイテムが配列内にあるかどうかを確認します。

if ([1, 2, 3, 4].includes(test.type)) {
    // Do something
}

サポートしているブラウザーにメソッドがない場合は、この polyfillArray#includesを使用できます。


~チルダ ショートカットの簡単な説明:

更新:includesメソッドができたので、~ハックを使用しても意味がありません。これがどのように機能するかを知りたい人や、他のコードで遭遇した人のために、ここに残しておきます。

indexOfの結果がisかどうかをチェックする代わりに>= 0、素敵なちょっとしたショートカットがあります:

if ( ~[1, 2, 3, 4].indexOf(test.type) ) {
    // Do something
}

これがフィドルです:http://jsfiddle.net/HYJvK/

これはどのように作動しますか?配列内にアイテムが見つかった場合、indexOfそのインデックスを返します。アイテムが見つからなかった場合は、 が返されます-1。あまり詳しく説明しません~が、 はビット単位の NOT 演算子0であり、のみを返し-1ます。

~戻り値を比較するよりも簡潔なので、ショートカットを使用するのが好きです。JavaScript にin_array(PHP に似た) ブール値を直接返す関数があればいいのにと思いますが、それは単なる希望的観測です (更新:現在はそうです。 と呼ばれていますincludes。上記を参照してください)。jQuery のinArrayは、PHP のメソッド シグネチャを共有していますが、実際にはネイティブindexOf機能を模倣していることに注意してください (これは、インデックスが本当に求めているものである場合、さまざまな場合に役立ちます)。

重要な注意:チルダ ショートカットの使用は、コードが十分に明確ではなく、絶対に避けるべきだと強く信じているため、論争に巻き込まれているようです(この回答のコメントを参照してください)。彼らの感情を共有する場合は、.indexOf(...) >= 0解決策に固執する必要があります。


少し長い説明:

JavaScript の整数は符号付きです。つまり、左端のビットは符号ビットとして予約されています。数値が正か負かを示すフラグ。a は1負です。

32 ビット バイナリ形式の正数のサンプルを次に示します。

1 :    00000000000000000000000000000001
2 :    00000000000000000000000000000010
3 :    00000000000000000000000000000011
15:    00000000000000000000000000001111

ここにそれらの同じ数値がありますが、負です:

-1 :   11111111111111111111111111111111
-2 :   11111111111111111111111111111110
-3 :   11111111111111111111111111111101
-15:   11111111111111111111111111110001

負の数の奇妙な組み合わせはなぜですか? 単純。負の数は正の数 + 1 の単純な逆数です。負の数を正の数に加算すると、常に が得られるはず0です。

これを理解するために、単純な 2 進演算を実行してみましょう。

に追加-1する方法は次の+1とおりです。

   00000000000000000000000000000001      +1
+  11111111111111111111111111111111      -1
-------------------------------------------
=  00000000000000000000000000000000       0

に追加-15する方法は次の+15とおりです。

   00000000000000000000000000001111      +15
+  11111111111111111111111111110001      -15
--------------------------------------------
=  00000000000000000000000000000000        0

それらの結果を得るにはどうすればよいでしょうか。学校で教えられたように、通常の足し算を行うことで、一番右の列から始めて、すべての行を足し合わせます。9合計が 1 桁の最大数 (10 進数では、2 進数では)よりも大きい場合、1剰余は次の列に繰り越されます。

お気づきのように、負の数をその正の数に加算すると、すべてが0s ではない一番右の列には常に 2 つ1の があり、それらを加算すると になり2ます。2 の 2 進表現は であり、 を次の列に10運び、最初の列に結果の a を入れます。左側の他のすべての列には が含まれる行が 1 つしかないため、前の列からの繰り越しは再び になり、それが繰り越されます...このプロセスは、一番左の列に到達するまで繰り返されます。持ち越されるものは行き場がなく、あふれて迷子になり、横にsが残ってしまいます。1011210

このシステムは2's Complementと呼ばれます。詳細については、こちらをご覧ください。

符号付き整数の 2 の補数表現


-12 の補数の速習コースが終わったので、2 進数表現が1すべて 's'である唯一の数であることに気付くでしょう。

ビットごとの NOT 演算子を使用する~と、指定された数値のすべてのビットが反転されます。0すべてのビットを反転することから戻る唯一の方法は、最初から1's' を使用することです。

したがって、これはすべて、 isの場合~nにのみ返されるという長々とした言い方でした。0n-1

于 2013-08-21T00:32:22.677 に答える
63

科学を使用する:コードを短く保ちながら、idfahが言ったこととこれを実行して最速にする必要があります:

~これはメソッドよりも高速です

var x = test.type;
if (x == 'itema' ||
    x == 'itemb' ||
    x == 'itemc' ||
    x == 'itemd') {
    //do something
}

http://jsperf.com/if-statements-test-techsin ここに画像の説明を入力 (上のセット: Chrome、下のセット: Firefox)

結論 :

可能性がほとんどなく、特定の可能性が発生する可能性が高いことがわかっている場合はif ||switch fall through、およびif(obj[keyval]).

可能性が多数あり、それらのいずれかが最も発生する可能性がある場合if(obj[keyval])、つまり、オブジェクト検索から最大のパフォーマンスを得てregex、それが適合するかどうかよりも、どの可能性が最も高いかを知ることはできません。

http://jsperf.com/if-statements-test-techsin/12

何か新しいことがあれば更新します。

于 2013-08-21T16:09:19.447 に答える
32

文字列と比較していてパターンがある場合は、正規表現の使用を検討してください。

そうしないと、コードを短くしようとすると、コードが難読化されるだけだと思います。見栄えを良くするために、単純に線を折り返すことを検討してください。

if (test.type == 'itema' ||
    test.type == 'itemb' ||
    test.type == 'itemc' ||
    test.type == 'itemd') {
    do something.
}
于 2013-08-21T01:00:41.647 に答える
16
var possibilities = {
  "itema": 1,
  "itemb": 1,
  "itemc": 1,
…};
if (test.type in possibilities) { … }

オブジェクトを連想配列として使用することはかなり一般的ですが、JavaScript にはネイティブ セットがないため、オブジェクトを安価なセットとして使用することもできます。

于 2013-08-21T00:44:27.290 に答える
15
if( /^item[a-d]$/.test(test.type) ) { /* do something */ }

またはアイテムが均一でない場合は、次のようになります。

if( /^(itema|itemb|itemc|itemd)$/.test(test.type) ) { /* do something */ }
于 2013-08-21T01:08:02.617 に答える
10

優れた回答ですが、そのうちの1つを関数でラップすることで、コードをはるかに読みやすくすることができます.

これは複雑な if ステートメントです。あなた (または他の誰か) が数年後にコードを読むと、何が起こっているのかを理解するためにセクションを探します。このレベルのビジネス ロジックを使用したステートメントを使用すると、何をテストしているのかを調べているときに、数秒間つまずくことがあります。このようなコードでは、スキャンを続行できます。

if(CheckIfBusinessRuleIsTrue())
{
    //Do Something
}

function CheckIfBusinessRuleIsTrue() 
{
    return (the best solution from previous posts here);
}

関数に明示的な名前を付けて、何をテストしているのかがすぐにわかるようにします。コードをスキャンして理解するのがはるかに簡単になります。

于 2013-08-27T20:18:07.453 に答える
4

すべての回答をJavascript Setに入れてから、そのセットを呼び出すことができ.contains()ます。

すべてのコンテンツを宣言する必要がありますが、インライン呼び出しは短くなります。

何かのようなもの:

var itemSet = new Set(["itema","itemb","itemc","itemd"]);
if( itemSet.contains( test.type ){}
于 2013-08-21T01:18:00.003 に答える
2

これを達成するための私のお気に入りの方法の 1 つは、underscore.js などのライブラリを使用することです...

var isItem = _.some(['itema','itemb','itemc','itemd'], function(item) {
    return test.type === item;
});

if(isItem) {
    // One of them was true
}

http://underscorejs.org/#some

于 2013-08-21T00:49:34.643 に答える
2

switchステートメントの代わりにステートメントを使用してifください:

switch (test.type) {

  case "itema":case "itemb":case "itemc":case "itemd":
    // do your process
  case "other cases":...:
    // do other processes
  default:
    // do processes when test.type does not meet your predictions.
}

Switch内の多くの条件を比較するよりも高速に動作します。if

于 2013-08-27T20:47:55.347 に答える
2

文字列の非常に長いリストの場合、このアイデアは数文字を節約します (実際に推奨するとは言いませんが、うまくいくはずです)。

test.type に出現しないことがわかっている文字を選択し、それを区切り文字として使用し、それらすべてを 1 つの長い文字列に貼り付けて、次を検索します。

if ("/itema/itemb/itemc/itemd/".indexOf("/"+test.type+"/")>=0) {
  // doSomething
}

文字列がさらに制約されている場合は、区切り文字を省略できます...

if ("itemaitembitemcitemd".indexOf(test.type)>=0) {
  // doSomething
}

...しかし、その場合は誤検知に注意する必要があります (たとえば、「embite」はそのバージョンで一致します)。

于 2013-08-27T21:16:58.033 に答える