値のリストに対して変数の等価性をチェックします


133

たとえばfoo、変数をチェックして、値の数が等しいかどうかを確認しています。例えば、

if( foo == 1 || foo == 3 || foo == 12 ) {
    // ...
}

ポイントは、それはそのような些細なタスクのためのかなり多くのコードであるということです。私は次のことを思いつきました:

if( foo in {1: 1, 3: 1, 12: 1} ) {
    // ...
}

しかし、オブジェクトのアイテムに冗長な値を指定する必要があるため、これは完全に私には魅力的ではありません。

誰かが複数の値に対して同等性チェックを行う適切な方法を知っていますか?


このような比較を行う理由を知ることが重要であるため、このようなものを決定するときは、より大きなコンテキストが関与する必要があると思います。
先のとがっ

まあ、私が作成しているゲームでは、どの関数を呼び出すかを決定するために、キーボードコードをチェックしています。ブラウザによっては、キーに表示されるキーコードが異なるため、複数の値と比較する必要があります。
pimvdb 2011年

複数のメソッドのパフォーマンステストをチェックし、論理演算子がrunkit.com/pramendra/58cad911146c1c00147f8d8dを獲得
Pramendra Gupta

回答:


175

あなたは配列を使うことができますindexOf

if ([1,3,12].indexOf(foo) > -1)

1
私はこれが好きです。> -1の使用を排除するために、プロトタイプを使用して「contains」関数を作成することも可能です。
pimvdb 2011年

1
@pimvdb:indexOfECMAScript 5版以降でのみ利用可能な独自の実装が必要になる場合があることに注意してください。
ガンボ

別の答えでは、これは、私はそれを知らなかった、だけでなく、実際としてのおかげで言及されている
pimvdb

「>」は「!==」よりも優れていますか?
マックスウォーターマン

117

ECMA2016では、includesメソッドを使用できます。それは私が見た中で最もきれいな方法です。(IEを除くすべての主要ブラウザーでサポートされています(Polyfillはリンクにあります)

if([1,3,12].includes(foo)) {
    // ...
}

4
変数if([a,b,c].includes(foo))または文字列の場合if(['a','b','c'].includes(foo))
Hastig Zusammenstellen 2017

変数の場合=> if([a,b,c].includes(foo))引用符が文字列にするため。あずきっく
iambinodstha

2
@BinodShrestha私が何かを欠落していない限り、それは私が書いたものだと思います。「変数用..または文字列...」
Hastig Zusammenstellen

16

提供された回答を使用して、私は次のようになりました:

Object.prototype.in = function() {
    for(var i=0; i<arguments.length; i++)
       if(arguments[i] == this) return true;
    return false;
}

それは次のように呼び出すことができます:

if(foo.in(1, 3, 12)) {
    // ...
}

編集:最近、この「トリック」に出くわしました。これは、値が文字列であり、特殊文字が含まれていない場合に役立ちます。特殊文字の場合、エスケープが原因で醜くなり、そのためエラーが発生しやすくなります。

/foo|bar|something/.test(str);

より正確に言うと、これは正確な文字列をチェックしますが、単純な等価性テストではさらに複雑になります。

/^(foo|bar|something)$/.test(str);

5
よし!私は驚いたことにin、JavaScriptのキーワードです。たとえば、実行function in() {}; in()すると、少なくともFirefoxでは構文エラーが発生しますが、コードがそうでない理由はわかりません。:-)
ベンブランク

3
また、を拡張するObject.prototypeことはfor (foo in bar)、残念なことに影響を与えるため、多くの場合、悪い習慣と見なされています。おそらくそれをに変更してfunction contains(obj) { for (var i = 1; i < arguments.length; i++) if (arguments[i] === obj) return true; return false; }、オブジェクトを引数として渡しますか?
Ben Blank

ご回答いただきありがとうございます。GoogleClosure Compilerも、このコード自体が正常に機能しているときにコンパイル中にエラーを返します。とにかく、ヘルパークラスはObject.prototype、あなたが言及するように、拡張よりもこの仕事を行うことができることが示唆されています。ただし、チェックの表記はとてもfoo.in(1, 2, "test", Infinity)簡単で、パイのように簡単なので、私はこの方法を好みます。
pimvdb

そして、関数を定義すると、in()Chromeでも通常の方法で失敗しますが、プロトタイプは機能します... :)
pimvdb

3
Object.prototypeの拡張はアンチパターンであり、使用すべきではありません。代わりに関数を使用してください。
ヴァーノン、

9

あなたがif(foo in L(10,20,30))そうであると定義Lするならば、あなたは書くことができます

var L = function()
{
    var obj = {};
    for(var i=0; i<arguments.length; i++)
        obj[arguments[i]] = null;

    return obj;
};

これは、以前の回答よりもさらに明確です。ありがとうございます。
pimvdb 2011年

2
プロトタイプ関数も配列/オブジェクトの「中に」あることに注意するのは賢明だと思います-したがって、配列/オブジェクトのプロトタイプに関数「remove」がある場合、コーディング'remove' in L(1, 3, 12)しないと、常にtrueを返しますリストに入れる「削除」を指定します。
pimvdb 2011年

7

これは簡単に拡張および読み取り可能です。

switch (foo) {
    case 1:
    case 3:
    case 12:
        // ...
        break

    case 4:
    case 5:
    case 6:
        // something else
        break
}

しかし、必ずしも簡単ではありません:)


実際にこの方法を使用したのは、各値の横にコメントを付けて、値が何に関連しているかを説明したかったためです。これは、これを実現する最も読みやすい方法でした。
ホルクロフト

@pholcroftは、各値が何に関連しているかを説明する必要がある場合は、列挙型またはクラスを作成し、わかりやすい名前を持つプロパティを記述します。
red_dorian

6
var a = [1,2,3];

if ( a.indexOf( 1 ) !== -1 ) { }

indexOfはコアECMAScriptにはないことに注意してください。IEのスニペットと、Array.prototype.indexOfをサポートしていない他のブラウザーが必要です。

if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(searchElement /*, fromIndex */)
  {
    "use strict";

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (len === 0)
      return -1;

    var n = 0;
    if (arguments.length > 0)
    {
      n = Number(arguments[1]);
      if (n !== n)
        n = 0;
      else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
        n = (n > 0 || -1) * Math.floor(Math.abs(n));
    }

    if (n >= len)
      return -1;

    var k = n >= 0
          ? n
          : Math.max(len - Math.abs(n), 0);

    for (; k < len; k++)
    {
      if (k in t && t[k] === searchElement)
        return k;
    }
    return -1;
  };
}

直接Mozillaのコピーです。リンクするのが面倒だった。developer.mozilla.org/en/JavaScript/Reference/Global_Objects/...
omuraliev MEDER

実際にビットをシフトしていないのにlenを定義するときにビットシフトする理由はありますか?ここで暗黙の強制が行われていますか?
jaredad7 2018


2

今、あなたはこのシナリオを解決するより良い解決策を持っているかもしれませんが、私が好んだ他の方法があります。

const arr = [1,3,12]
if( arr.includes(foo)) { // it will return true if you `foo` is one of array values else false
  // code here    
}

私は、インデックスをチェックする必要があるindexOfチェックよりも上記のソリューションを優先しました。

ドキュメントを含む

if ( arr.indexOf( foo ) !== -1 ) { }

1

私は受け入れられた答えが好きでしたが、配列も取得できるようにするのは素晴らしいと思いましたので、これを次のように拡張しました。

Object.prototype.isin = function() {
    for(var i = arguments.length; i--;) {
        var a = arguments[i];
        if(a.constructor === Array) {
            for(var j = a.length; j--;)
                if(a[j] == this) return true;
        }
        else if(a == this) return true;
    }
    return false;
}

var lucky = 7,
    more = [7, 11, 42];
lucky.isin(2, 3, 5, 8, more) //true

あなたは、変更することにより、型の強制を削除することができます=====


1

Underscoreにアクセスできる場合は、以下を使用できます。

if (_.contains([1, 3, 12], foo)) {
  // ...
}

contains ロダッシュでも使用されていました(V4より前)、今は使用する必要があります includes

if (_.includes([1, 3, 12], foo)) {
  handleYellowFruit();
}

1

これは、小さなヘルパーアラー関数です。

const letters = ['A', 'B', 'C', 'D'];

function checkInList(arr, val) {
  return arr.some(arrVal => val === arrVal);
}

checkInList(letters, 'E');   // false
checkInList(letters, 'A');   // true

詳細はこちら...


非常に優れたアプローチ:アイデアから始めて、ヘルパー関数なしでも実行できます:const valToCheck = 'E'; const check = ['A', 'B', 'C', 'D'].some(option => option === valToCheck); // false
Giorgio Tempesta

しかし、私は、私が見つけたコードの微調整を開始したらincludes、@アリスターの答えのように、より良いオプションになります:const valToCheck = 'E'; const check = ['A', 'B', 'C', 'D'].includes(valToCheck); // false
ジョルジョ・テンペスタを

0

私は単にjQueryのinArray関数と値の配列を使用してこれを実現しました。

myArr = ["A", "B", "C", "C-"];

var test = $.inArray("C", myArr)  
// returns index of 2 returns -1 if not in array

if(test >= 0) // true

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.