web-dev-qa-db-ja.com

JSのネストされた三項演算子の代替

私は個人的に三項演算子が大好きです。私の考えでは、複雑な式を非常に簡単に消化できると私は考えています。これを取る:

  Word = (res.distance === 0) ? 'a'
    : (res.distance === 1 && res.difference > 3) ? 'b'
    : (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) ? 'c'
    : 'd';

ただし、このプロジェクトのESLINTルールでは、ネストされた3項演算子は禁止されているため、上記を取り除く必要があります。

私はこのアプローチの代替案を見つけようとしています。私は本当にそれを巨大なif/elseステートメントに変えたくありませんが、他のオプションがあるかどうかはわかりません。

33
dthree

ここでの選択肢は基本的に次のとおりです。

  1. if/elseしたくない
  2. switchif/elseの組み合わせ

私は妥当なルックアップマップオプションを考え出そうとしましたが、かなり早く無理になりました。

私は#1に行きますが、それほど大きくはありません。

if (res.distance == 0) {
    Word = 'a';
} else if (res.distance == 1 && res.difference > 3) {
    Word = 'b';
} else if (res.distance == 2 && res.difference > 5 && String(res.key).length > 5) {
    Word = 'c';
} else {
    Word = 'd';
}

すべての中括弧と垂直サイズが気になる場合、それらがないと、条件演算子バージョンとほぼ同じくらい簡潔になります。

if (res.distance == 0) Word = 'a';
else if (res.distance == 1 && res.difference > 3) Word = 'b';
else if (res.distance == 2 && res.difference > 5 && String(res.key).length > 5) Word = 'c';
else Word = 'd';

(私はそれを主張していません。中括弧を省略したり、ifに続くステートメントを同じ行に置いたりすることを決して主張しませんが、他の人は異なるスタイルの見方を持っています。)

#2は、私の考えではより不格好ですが、おそらく他の何よりもスタイルコメントです。

Word = 'd';
switch (res.distance) {
    case 0:
        Word = 'a';
        break;
    case 1:
        if (res.difference > 3) {
            Word = 'b';
        }
        break;
    case 2:
        if (res.difference > 5 && String(res.key).length > 5) {
            Word = 'c';
        }
        break;
}

そして最後に、私はこれを擁護していますではありません、JavaScriptのswitchが異常であるという事実を利用できます [〜#〜] b [〜#〜] -構文言語ファミリ:caseステートメントはにすることができ、スイッチと照合されますソースコード順の値:

switch (true) {
    case res.distance == 0:
        Word = 'a';
        break;
    case res.distance == 1 && res.difference > 3:
        Word = 'b';
        break;
    case res.distance == 2 && res.difference > 5 && String(res.key).length > 5:
        Word = 'c';
        break;
    default:
        Word = 'd';
        break;
}

醜いですか? :-)

17
T.J. Crowder

私の好みでは、注意深く構造化されたネストされた三項は、これらすべての厄介なifとswitchに勝っています。

const isFoo = res.distance === 0;
const isBar = res.distance === 1 && res.difference > 3;
const isBaz = res.distance === 2 && res.difference > 5 && String(res.key).length > 5;

const Word =
  isFoo ? 'a' :
  isBar ? 'b' :
  isBaz ? 'c' :
          'd' ;

すぐに呼び出される関数式 を記述して、少し読みやすくすることができます。

const Word = (() =>  {
  if (res.distance === 0) return 'a';
  if (res.distance === 1 && res.difference > 3) return 'b';
  if (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) return 'c';
  return 'd';
})();

リンクへのリンク

2
Yo Wakita

すべての真の条件が真の値に評価される場合(したがって、疑問符とセミコロンの間の値がブール値に強制される場合、真に評価されます...)、3項式にfalseを偽の式として返すようにすることができます。次に、ビット単位のor(||)演算子を使用して、デフォルト値を返す最後の条件まで、次の条件をテストします。

以下の例では、「condsXXX」配列は条件を評価した結果を表しています。 「conds3rd」は3番目の条件が真であることをシミュレートし、「condsNone」は条件が真でないことをシミュレートします。実際のコードでは、代入式に「インライン化された」条件があります。

var conds3rd = [false, false, true];
var condsNone = [false, false, false];

var val3rd = (conds3rd[0] ? 1 : false) ||
  (conds3rd[1] ? 2 : false) ||
  (conds3rd[2] ? 3 : 4);

var valNone = (condsNone[0] ? 1 : false) ||
  (condsNone[1] ? 2 : false) ||
  (condsNone[2] ? 3 : 4);

alert(val3rd);
alert(valNone);

あなたの例は以下のようになるかもしれません:

Word = ((res.distance === 0) ? 'a' : false) ||
    ((res.distance === 1 && res.difference > 3) ? 'b' : false) ||
    ((res.distance === 2 && res.difference > 5 && String(res.key).length > 5) ? 'c' : 'd';

余談ですが、見栄えの良いコードだとは思いませんが、純粋に3項演算子を使用するのと同じです...

2
Amit
Word = (res.distance === 0) ? 'a'
: (res.distance === 1 && res.difference > 3) ? 'b'
: (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) ? 'c'
: 'd';

これは古い質問ですが、これは私がそれを行う方法です...私はデフォルトのケースから始めて、変数を変更するか、必要に応じて変更せずに渡します。

var Word = 'd';
Word = (res.distance === 0) ? 'a' : Word;
Word = (res.distance === 1 && res.difference > 3) ? 'b' : Word
word = (res.distance === 2 && res.difference > 5 && String(res.key).length > 5) ? 'c' : Word;
2
K McCabe

ネストされた三項式でconstを使用する場合は、三項を関数式で置き換えることができます。

const res = { distance: 1, difference: 5 };

const branch = (condition, ifTrue, ifFalse) => condition?ifTrue:ifFalse;
const Word = branch(
  res.distance === 0,    // if
  'a',                   // then
  branch(                // else
    res.distance === 1 && res.difference > 3,   // if
    'b',                                        // then
    branch(                                     // else
      res.distance === 2 && res.difference > 5,   // if
      'c',                                        // then
      'd'                                         // else
    )
  )
);

console.log(Word);

または、分解による名前付きパラメーターの使用...

const branch2 = function(branch) {
  return branch.if ? branch.then : branch.else;
}

const fizzbuzz = function(num) {
  return branch2({
    if: num % 3 === 0 && num % 5 === 0,
    then: 'fizzbuzz',
    else: branch2({
        if: num % 3 === 0,
        then: 'fizz',
        else: branch2({
          if: num % 5 === 0,
          then: 'buzz',
          else: num
        })
      })
  });
}

console.log(
  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16].map(
    cv => fizzbuzz(cv)
  )
);

...編集:pythonのような式の場合、次のようにモデル化する方がわかりやすいかもしれません。

const res = { distance: 1, difference: 5 };

const maybe = def => ({
  if: expr => {
    if (expr) {
      return { else: () => def };
    } else {
      return { else: els => els };
    }
  }
});
const Word = maybe('a').if(res.distance === 0).else(
  maybe('b').if(res.distance === 1 && res.difference > 3).else(
    maybe('c').if(res.distance === 2 && res.difference > 5).else('d')
  )
);
console.log(Word);
1
Doug Coburn

これらのケースでは、switch(true)ステートメントを使用しています。私の意見では、この構文はネストされたif/else演算子よりも少しエレガントに感じられます

switch (true) {
  case condition === true :
    //do it
    break;
  case otherCondition === true && soOn < 100 :
    // do that
    break;
}
0
ap-o