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

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

ただいまの
回答率

87.61%

【考え方】ifの条件をスマートにしたい / 3つの値のバリデーション

解決済

回答 5

投稿

  • 評価
  • クリップ 1
  • VIEW 874

score 1879

直接コードとは関係ないのですが、考え方について質問させてください。


A, B, C の3つの変数があり、

  1. A, B, C のすべてがundefinedなら無視
  2. A, B, C のいずれかに値が入っていて、かつ、どれか一つにでもundefinedがあればエラー
  3. A, B, C の全てに値があれば問題ない(無視)

というif文を書きたいのですが、普通にそのまま書くと、

if ( (A === undefined || B === undefined || C === undefined) && (A !== undefined || B !== undefined || C !== undefined) ) {
    // error
} else {
    // OK
}

となります。(あれ?あってる……?)
なる気がします。

しかし、このif文はかなり冗長ですし、見やすいと言えません。
この場合、他にどのような書き方が思いつきますでしょうか?
自分では思いつかず……

お知恵をお貸しいただけますと幸いです。
よろしくお願いいたします!

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • miyabi-sun

    2019/03/28 17:46

    PHPにはundefinedはありませんよ

    キャンセル

  • nnahito

    2019/03/28 17:51

    タグミスでした!ごめんなさい

    キャンセル

回答 5

checkベストアンサー

+7

条件を変数として切り出すことで可読性が良くなると思われます。

以下はいかがでしょか。

// 条件①
var isAllUndefind = (A === undefined && B === undefined && C === undefined);
// 条件③
var isAllInputed = (A !== undefined && B !== undefined && C !== undefined);

if (isAllInputed || isAllUndefind) {
    // ①か③に該当する場合
    // OK
} else {
    // ①と③に該当しない→②の場合
    // error
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/28 17:50

    それだあああああああ!!!
    ありがとうございます!!!

    キャンセル

+6

1. A, B, C のすべてがundefinedなら無視
2. A, B, C のいずれかに値が入っていて、かつ、どれか一つにでもundefinedがあればエラー
3. A, B, C の全てに値があれば問題ない(無視)

実際のケースではこういう状況は実務ではほぼ出てきません。
1番目は何も処理をしないのですぐに逃げる、
2番目はエラーを投げる、3番目は実際に実行。

この条件ならガード節を使って2秒で実装出来ますし、
そうなっていないなら、3つの引数が全てundefinedにも関わらず処理を継続しなければならない既存ロジックがおかしいケースが殆どです。
上流の方の流れを変えてやるほうが良いでしょう。

const awesomeFunc = (a, b, c) => {
  if (a === undefined && b === undefined && c === undefined) return;
  if (a !== undefined) throw new Error('a is undefined.');
  if (b !== undefined) throw new Error('b is undefined.');
  if (c !== undefined) throw new Error('c is undefined.');
  // main logic
}

ここからは質問文に沿って動作させなければならない状況に遭遇したとして考えます。

過度なガード節はあまりよろしいものではありません。
あなたは数学の時間に、適当にありとあらゆる公式を連れてきて、
闇雲に計算してみて答えに近いものを解答用紙に書くような答え方をしていましたか?

そうではなく、適切な公式を持ってきて数式を綺麗な形に整形して回答していましたよね?
プログラミングの世界でもそれは同じです。

if文はただし書き、例外を取り扱うようなもので、
何の関数をいつ使うのかは上流の工程でしっかり制御するべきです。
つまり、質問文の状況に陥るのはそもそもプログラミングが下手だからでしょ?という結論になります。


どうしても初期の構想で動作しなければならないのであれば、
最低限、実行する関数と判定関数を分けましょう。

また実行しても良いか悪いかわからないのに、
とりあえず実行してみるなんて、
わけも分からず自爆スイッチを押すバカ職員です。

try-catchの構文は、ネットワーク通信やデータベースへの問い合わせ等、
プログラムのロジックが完璧に動作するにも関わらず、
エラーが帰ってきてやむを得ず挙動を修正しなければならないケースで用いられるべきものです。

関数として用意するならこんな感じ。

const isPossible = (a, b, c) => {
  if (a === undefined && b === undefined && c === undefined) return true;
  if (a !== undefined || b !== undefined && c !== undefined) return false;
  return true;
}

const awesomeFunc = (a, b, c) => {
  // main logic
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

every メソッドを使ってみました。

if ( !( [A,B,C].every( x => x===undefined ) || [A,B,C].every( x => x !== undefined ) ) ){


Array.prototype.every() - JavaScript | MDN

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/28 17:52

    あ、ご解決でしたか。

    キャンセル

+3

自分が考えたのは、こんな方法です。

// まず、それぞれがundefinedかを抽出する
const aUndef = A === undefined, bUndef = B === undefined, cUndef = C === undefined;

// 「undefinedかどうか」がすべて等しいなら
if(aUndef === bUndef && aUndef === cUndef){
  // 略
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

改善案

条件をシンプルに考えて、「undefinedの数をカウントすれば良い」という結論に達しました。

function everyOrNone (...array) {
  let count = 0;

  for (let value of array) {
    count += value === undefined;
  }

  return count === 0 || count === array.length;
}

console.log(everyOrNone());                // true
console.log(everyOrNone(1, 2, 3));         // true
console.log(everyOrNone(1, undefined, 3)); // false
console.log(everyOrNone(undefined, undefined, undefined)); // true

条件式の妥当性

余談ですが、「undefined以外は真」というアルゴリズムには疑問を感じます。
通常、変数には期待する型があるので、例えば、Number型を期待するなら、「Number型以外の型」は全てNGです。
私なら「undefined か否か」ではなく、「Number型か否か」を条件式にします。

typeof a === "number"

Re: nnahito さん

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 87.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る