【JavaScriptクイズ】第2問:if文を減らすには

2023/03/27に公開

JavaScriptの文法や便利な使い方について、気軽なクイズ形式で解説する記事を書いていきます。

今回のテーマは「if文の整理」です。では、さっそく問題です!

問題

JavaScriptを使って、次のような形式のオブジェクトで「長さ」を表すものとします。

// これは「150ミリメートル」を表す
{
  unit: "mm",
  value: 150
};

{ // これは「150センチメートル」を表す
  unit: "cm",
  value: 150
};

このとき、「長さが1メートルを超えるか」を判定する関数isGreaterThan1Meterを作りました。

quiz.js
"use strict";

function isGreaterThan1Meter(length) {
  if (length.unit === "mm") {
    if (length.value > 1000) {
      return true;
    }
  }

  if (length.unit === "cm") {
    if (length.value > 100) {
      return true;
    }
  }

  return false;
}

let length1 = { // 150ミリメートル
  unit: "mm",
  value: 150
};
console.log("length1: " + isGreaterThan1Meter(length1));

let length2 = { // 150センチメートル
  unit: "cm",
  value: 150
};
console.log("length2: " + isGreaterThan1Meter(length2));

このプログラムを実行すると、以下のような出力を得られます。

実行結果
length1: false
length2: true
  • length1は150ミリメートルで、1メートルより大きくないのでfalse
  • length2は150センチメートルで、1メートルより大きいのでtrue

という結果です。

さて、関数の内側にはif文が4つ見えると思います。実行結果が変わらないように気を付けながら、if文の数をできるだけ減らしてください。いくつまで減らせますか?

ヒントを見る?

まずは「AND条件(&&)」を使って、ifのネスト(入れ子)を減らしてみましょう。

答えを見る?

次のようにすれば、if文は1つもなくなります。

quiz.js
"use strict";

function isGreaterThan1Meter(length) {
  return (
    ((length.unit === "mm") && (length.value > 1000)) ||
    ((length.unit === "cm") && (length.value > 100))
  );
}

let length1 = { // 150ミリメートル
  unit: "mm",
  value: 150
};
console.log("length1: " + isGreaterThan1Meter(length1));

let length2 = { // 150センチメートル
  unit: "cm",
  value: 150
};
console.log("length2: " + isGreaterThan1Meter(length2));

解説

プログラムをよく見ながら、順を追ってif文を整理していきましょう。

ステップ1:ANDでまとめる

まず、ミリメートル単位の長さを処理している、if文のネストに注目しましょう。

  if (length.unit === "mm") {
    if (length.value > 1000) {
      return true;
    }
  }

この2つのif文は、外側の条件が成立し、かつ内側の条件も成立したかどうかをチェックしています。したがて、「AND条件(&&)」を使えば1つにまとめられます。

  if ((length.unit === "mm") && (length.value > 1000)) {
    return true;
  }

センチメートル単位の長さを処理しているほうのif文についても……

  if (length.unit === "cm") {
    if (length.value > 100) {
      return true;
    }
  }

同じようにすれば、1つにまとめられますね。

  if ((length.unit === "cm") && (length.value > 100)) {
    return true;
  }

これで、4つあったif文は2つに減りました。

ステップ2:ORでまとめる

ここまでで、if文は次のようになっています。

  if ((length.unit === "mm") && (length.value > 1000)) {
    return true;
  }

  if ((length.unit === "cm") && (length.value > 100)) {
    return true;
  }

よく見ると、次のことが分かるでしょう。

  • 条件が成立したときの処理内容は、どちらのif文も同じ(trueを返す)
  • 2つのif文の条件が、両方とも成立するケースはない(1つ目のif文の条件が成立すると、その場でreturnしてしまうため)

そのため、次のように「OR条件(||)」で1つにまとめてしまっても、結果は変わりません。

  if (
    ((length.unit === "mm") && (length.value > 1000)) ||
    ((length.unit === "cm") && (length.value > 100))
  ) {
    return true;
  }

これで、if文は1つになりました。でも、まだ終わりではありません!

ステップ3:式だけにする

if文が1つになって、関数全体がどうなったか観察してみましょう。

function isGreaterThan1Meter(length) {
  if (
    ((length.unit === "mm") && (length.value > 1000)) ||
    ((length.unit === "cm") && (length.value > 100))
  ) {
    return true;
  }

  return false;
}

よく見ると、この関数は次のようになっています。

  • if文の条件が成立したら、trueを返す
  • そうでなければ、falseを返す

この処理には、少し冗長な部分があります。そもそも「if文の条件が成立する」とは、「条件式がtrueになる」ことだからです。

つまり、if文をまったく書かずに、次のようにできます。

function isGreaterThan1Meter(length) {
  return (
    ((length.unit === "mm") && (length.value > 1000)) ||
    ((length.unit === "cm") && (length.value > 100))
  );
}

まとめ

今回は、4つあるif文を「いくつまで減らせますか?」と出題しておいて、最終的に1つもなくなってしまうというのが答えでした。どうだったでしょうか?

プログラムは、無理をして短くまとめようとすると、かえって読みづらくなってしまうことも少なくありません。でも今回は、スッキリと分かりやすいプログラムにできたのではないかと思います。

if文は「条件分岐」といって、プログラムの流れが枝分かれする部分にあたります。そのため、使いすぎると処理が複雑になり、動作確認も大変になってしまうかもしれません。ないほうがスッキリするif文は、なくしてしまうのがおすすめです。

なお、if文はJavaScriptに限らず多くのプログラミング言語に採用されている文法です。下記のページでは、C言語のif文について取り上げています。

https://curiocube.team-aries.com/progtips-ch13-wrongif/

ほかのプログラミング言語についても気になるという人は、下記の本もチェックしてみてください。こちらでは、10種類のプログラミング言語を比較できます!

https://zenn.dev/teamariesdotcom/books/af56bae422969b

Discussion