2017-05-05 11 views
0

具体的にはswitchというステートメントを使用する方が良いかどうか疑問に思っています。if/elseとswitchの使用

私はAlexa Custom Skillを書いています。利用可能な情報(別名スロット)に応じて適切な意図に「リダイレクト」する必要があります。以下は、私は現在、(if/elseを使用)したものである:

if (_type === "IntentRequest") { 

    this.handler.state = states.START; 
    if (_slots.indexOf("address") != -1) { 
     this.emitWithState("GoingToAddressIntent"); 
    } else if (_slots.indexOf("place") != -1) { 
     this.emitWithState("GoingToPlaceIntent"); 
    } else if (_slots.indexOf("type") != -1) { 
     this.emitWithState("GoingToTypeIntent"); 
    } else if (_slots.indexOf("purpose") != -1) { 
     this.emitWithState("GoingToPurposeIntent"); 
    } else { 
     this.emit("Unhandled"); 
    } 

} 

私は_slotsは、4つの要素、[ "address", "place", "type", "purpose" ]の任意の順列の配列であることを期待しています。したがって、[ "address" ]から[ "place", "purpose" ]などまでは何でもかまいませんが、は常に同じ順番でです(たとえば、[ "purpose", "address" ]は起こりません)。

情報の「階層」があるため、比較の順序は重要です。 "アドレス"スロットが存在する場合は、emit"GoingToAddressIntent"にかかわらず、の他のスロットを使用する必要があります。この要件を前提として、文字列の配列をブール値の配列に「変換」するための余分なコード行を必要とせずに、より簡単で読みやすいswitchステートメントを使用すると考えました。階層&が明示的に評価されていることを明確に示しています。私が行うことができます:私は常にtrueリテラル(4すべてのためのスロットが最初に出現する位置のインデックスを取得するためにindexOf()を使用して、ブール値の配列を定義するために余分なラインを持っている場合には

if (_type === "IntentRequest") { 

    this.handler.state = states.START; 
    slots = [ 
     _slots.indexOf("address") != -1, 
     _slots.indexOf("place") != -1, 
     _slots.indexOf("type") != -1, 
     _slots.indexOf("purpose") != -1 
    ] 

    switch(slots.indexOf(true)) { 
    case 0: 
     this.emitWithState("GoingToAddressIntent"); 
     break; 
    case 1: 
     this.emitWithState("GoingToAddressIntent"); 
     break; 
    case 2: 
     this.emitWithState("GoingToTypeIntent"); 
     break; 
    case 3: 
     this.emitWithState("GoingToPurposeIntent"); 
     break; 
    default: 
     this.emit("Unhandled"); 
    } 

} 

を...階層の順に)、switchステートメントで実行します。しかし、私はこれが長期的な維持可能なプロジェクトになりたいと思っているので、このケースでは最高のプログラミングの練習が何であるか、そしてその理由は専門家に尋ねたかったのです。また、私は彼らの洞察から何かを学ぶことができると信じていました。


あなたは、これがSE上の別のコミュニティに移行する必要があると思われる場合のコメントを残したが、私のresearch(3歳であるが)から、私はちょうど100%自信がないんだけど(これは問題ないはずと信じてください。この)。

+0

なぜ番目のバージョンはありません'_slots'が配列の場合は' .hasOwnProperty() 'を使いますか? (それぞれの要素に対して '.indexOf()!= - 1'を使ってブール値の配列を構築してはいけませんか?)いずれの場合でも、2つのバージョンの選択は意見の問題です。 – nnnnnn

+0

@nnnnnn違いがありますか?私は 'in'、' hasOwnProperty() '、' indexOf()!= -1'は本質的に同じものを達成します( 'in'はそれ自身の警告があります)。 – spicypumpkin

+0

常に優先順位が高い場合、' _slots'のすべての要素をチェックする必要はありません。最初の要素をチェックし、それに応じて動作する必要があります。あなたがそうするなら、スイッチは理にかなっています。 – RJM

答えて

4

彼らは_slotsで優先度の高い順にいつもなら、多分あなたは、あなたが放出しようとしている状態にハッシュマップを作ることができる...

const map = { 
    address: "GoingToAddressIntent", 
    place: "GoingToPlaceIntent", 
    type: "GoingToTypeIntent", 
    purpose: "GoingToPurposeIntent" 
}; 

const state = map[_slots[0]]; 
if (state) { 
    this.emitWithState(state); 
} else { 
    this.emit("Unhandled"); 
} 
+0

オブジェクトリテラルは、「ハッシュマップ」ではなく**無秩序**の名前と値のペアの集合です) "それがあなたが望むなら、[real * Map *](http://ecma-international.org/ecma-262/7.0/index.html#sec-map-constructor)を使用してください;-) – RobG

1

switch文の例は使用しません。人々はあなたがしようとしていることを理解することができましたが、それはかなり畳み込まれているようです。主にバックエンドコードでswitch文を使っていますが、ここでうまくいくと思います。 if/elseのグループもうまくいきます。なぜなら、4つのケースで作業する必要があるからです。これはあなたが尋ねていることなので、switch文でロールバックします。

あなたの説明に基づいて、あなたが得る最初の価値は異なるかもしれませんが、注文は常に同じになるでしょう。ですから、解決策は単に最初の価値をつかんで、それを切り換えることです。

if (!!slots.length) { 
    var keyword = slots[0]; 
    switch (keyword) { 
    case 'address': 
     this.emitWithState("GoingToAddressIntent"); 
     break; 
    case 'place': 
     this.emitWithState("GoingToPlaceIntent"); 
     break; 
    case 'type': 
     this.emitWithState("GoingToTypeIntent"); 
     break; 
    case 'purpose': 
     this.emitWithState("GoingToPurposeIntent"); 
     break; 
    default: 
     this.emit('Unhandled'); // I typically throw an exception here 
    } 
} 
+0

答えをありがとう! 'Unhandled'のコメントに関しては、それは本質的に例外をスローするAlexaのバージョンです:( – spicypumpkin

関連する問題