文字列がJavaScriptのリストにあるかどうかを判別


263

SQLでは、文字列が次のようなリストにあるかどうかを確認できます。

Column IN ('a', 'b', 'c')

これをJavaScriptで行うための良い方法は何ですか?これを行うのはとても不格好です:

if (expression1 || expression2 || str === 'a' || str === 'b' || str === 'c') {
   // do something
}

そして、私はこれのパフォーマンスや明確さについてはわかりません:

if (expression1 || expression2 || {a:1, b:1, c:1}[str]) {
   // do something
}

または、switch関数を使用することもできます。

var str = 'a',
   flag = false;

switch (str) {
   case 'a':
   case 'b':
   case 'c':
      flag = true;
   default:
}

if (expression1 || expression2 || flag) {
   // do something
}

しかし、それは恐ろしい混乱です。何か案は?

この場合、企業のイントラネットページ用であるため、Internet Explorer 7を使用する必要があります。その['a', 'b', 'c'].indexOf(str) !== -1ため、何らかの構文糖なしではネイティブで動作しません。


1
「string is in list」と「array contains a object」の違いは何ですか?
のMichałPerłakowski

2
@Gothdoリストは常に配列であるとは限らず、文字列はオブジェクトではないのですか?どうすればもっと明確になりますか?
ErikE 2017年

@ErikEもしこれがあなたがメモで言及したものである場合、この質問は閉じられるべきであり、それ以上の報奨金/回答は許可されるべきではありません。すでに投稿された回答は、だれでも助けを得るのに十分です。
Vikasdeep Singh

@VicJordanコメントが適用されなくなったため、コメントを削除したい場合があります。
ErikE

回答:


280

あなたは呼び出すことができますindexOf

if (['a', 'b', 'c'].indexOf(str) >= 0) {
    //do something
}

15
唯一の問題Array.prototype.indexOfは、IEでは機能しないことです。残念ながら、IE8にもこのメソッドがありません。
CMS

2
ただし、必要に応じて定義できます。soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorerを
Jason Hall

ここでは「本物」の商品です。developer.mozilla.org/en/Core_JavaScript_1.5_Reference/...
ErikE

8
@ImJasonH:そのページのコードは本当に悪いIMHOです。たとえば、Array.indexOfオーバーライドする前に存在するかどうかを確認しますArray.prototype.indexOfが、同じものではありません。Mozillaによって作成された実装は、developer.mozilla.org
CMS

1
@ CMS、@ Emtuciforを聞いてください。Mozillaの実装の方がはるかに優れています。
Jason Hall

230

EcmaScript 6

ES6を使用している場合は、アイテムの配列を作成し、次を使用できますincludes

['a', 'b', 'c'].includes('b')

これは、以上のいくつかの固有の利点があるindexOf、それはの存在のために適切にテストすることができるのでNaN、リスト内、およびこのような中間の一つとして欠けている配列要素を一致させることが可能[1, , 2]にしますundefined。などのJavaScript型付き配列でincludesも機能しますUint8Array

ブラウザーサポート(IEやEdgeなど)が心配な場合は、CanIUse.Com確認Array.includesできます。不足しているブラウザーまたはブラウザーバージョンを対象にする場合はincludesポリフィル用にpolyfill.io をお勧めします。

アレイなし

isInList次のように新しいプロパティを文字列に追加できます。

if (!String.prototype.isInList) {
   String.prototype.isInList = function() {
      let value = this.valueOf();
      for (let i = 0, l = arguments.length; i < l; i += 1) {
         if (arguments[i] === value) return true;
      }
      return false;
   }
}

次に、次のように使用します。

'fox'.isInList('weasel', 'fox', 'stoat') // true
'fox'.isInList('weasel', 'stoat') // false

でも同じことができますNumber.prototype

Array.indexOf

最新のブラウザを使用している場合は、indexOf常に機能します。ただし、IE8以前では、ポリフィルが必要です。

indexOf-1を返す場合、アイテムはリストにありません。ただし、このメソッドはを適切にチェックしないことに注意してください。NaN明示的undefinedに一致することはできますが、欠落している要素をundefined配列のように一致させることはできません[1, , 2]

IEのポリフィル、indexOfまたはincludesサポートされていないその他のブラウザー/バージョン

上記のpolyfill.ioのようなサービスを使用したくない場合は、いつでも独自のソースコード標準に準拠したカスタムポリフィルを含めることができます。たとえば、Mozilla Developer Networkにはの1つがありindexOfます。

Internet Explorer 7のソリューションを作成する必要があったこの状況でindexOf()は、標準に準拠していない関数の"独自の"より単純なバージョンを "ロールバック" しました。

if (!Array.prototype.indexOf) {
   Array.prototype.indexOf = function(item) {
      var i = this.length;
      while (i--) {
         if (this[i] === item) return i;
      }
      return -1;
   }
}

しかし、Array.prototype長期的には修正が最善の答えだとは思いません。JavaScriptの変更ObjectArrayプロトタイプは重大なバグにつながる可能性があります。自分の環境で安全かどうかを判断する必要があります。主な注意点は、(Array.prototypeにプロパティが追加されている場合に)配列を反復するfor ... inと、新しい関数名がキーの1つとして返されることです。

Array.prototype.blah = function() { console.log('blah'); };
let arr = [1, 2, 3];
for (let x in arr) { console.log(x); }
// Result:
0
1
2
blah // Extra member iterated over!

コードは動作するかもしれませんが、将来誰かがサードパーティのJavaScriptライブラリまたはプラグインを追加した瞬間に、継承されたキーに対して熱心に保護していなければ、すべてが壊れる可能性があります。

その破損を回避するための古い方法は、オブジェクトが実際に非継承されたプロパティとしてそれを持っているかどうかを確認するために、それぞれの値をチェックするために、列挙中に、あるif (arr.hasOwnProperty(x))だけにしているとの仕事x

この余分なキーの問題を回避する新しいES6の方法ofin、の代わりにを使用することですfor (let x of arr)。ただし、すべてのコードとサードパーティのライブラリがこのメソッドに厳密に従うことを保証できない場合を除いて、この質問の目的には、おそらくincludes上記のように使用することをお勧めします。


2
MDN が提供する別の良いポリフィルがありindexOfます。基本的には同じことを行いますが、簡単に評価できるようにいくつかの短絡があります。
KyleMit 14年

1
反対投票者:コメントしてください。これの問題は何ですか?この関数は標準に準拠しておらず、準拠しようとはしていません。
ErikE、2015年

:あなたはすでに@KyleMitリンクによって指摘ポリフィルのようにテストした何かを使用する必要がありdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
lmiguelmh

@lmiguelmh Mozillaのドキュメント自体から、私がリンクを投稿した「ポリフィル」はどうですか?いずれにせよ、この関数は非常に単純なので、テストについてあまり心配していません。また、「テスト済み」の関数を使用するのではなく、自分が使用するものはすべてテストする必要があります。だからあなたのコメントは少し見当違いです。私の機能で特定の欠陥を特定しましたか?
ErikE 2016年

@ErikE正解です。この関数は無効であり、回答を使用している人は誰でも知っているはずです。「答え」を探していたので、そもそもあなたのリンクは
見つかりませんでした

53

ほとんどの答えはArray.prototype.indexOf方法を示唆していますが、唯一の問題はそれが機能しないことです任意の IE9の前にIEのバージョン。

別の方法として、すべてのブラウザで機能する2つのオプションを残しておきます。

if (/Foo|Bar|Baz/.test(str)) {
  // ...
}


if (str.match("Foo|Bar|Baz")) {
  // ...
}

うーん、言及してくれてありがとう、CMS。たまたまこれが企業のイントラネット用であり、彼らが使用しているのは...何だと思いますか... IE。正規表現メソッドは私に意欲を与えるので、ループする関数を作成するか、私の投稿(3番目のコードブロック)で提案したオブジェクトメソッドを使用する必要があります。
ErikE 2010年

13
これは一致します"HiFooThere"- /^(?:Foo|Bar|Baz)$/代わりに使用します(文字列の先頭、非キャプチャグループ、文字列の末尾)。
TrueWill、2015

indexOfMDNによると、IE 9以降でサポートされています。
krock

28

配列には、indexOf文字列の検索に使用できるメソッドがあります。

js> a = ['foo', 'bar', 'baz']
foo,bar,baz
js> a.indexOf('bar')
1
js> a.indexOf('quux')
-1

3
これは古いブラウザでは失敗します。
epascarello、2010年

おっと...これがIEで機能しないことを伝えるのは良かったでしょう。:)
ErikE 2010年

2
@epascarello:古いブラウザだけでなく、IE8 でも IEで失敗します :(
CMS

12

私が使ったトリックは

>>> ("something" in {"a string":"", "somthing":"", "another string":""})
false
>>> ("something" in {"a string":"", "something":"", "another string":""})
true

あなたは次のようなことをすることができます

>>> a = ["a string", "something", "another string"];
>>> b = {};
>>> for(var i=0; i<a.length;i++){b[a[i]]="";} /* Transform the array in a dict */
>>> ("something" in b)
true

ボイジャーは、私の質問の3番目のコードブロックが示したように、単に項目を逆参照しようとするよりも「速く」/「遅く」/「より良く」/「もっと悪く」使用していますか?また、ループする場合は、その時点で要素が配列にあるかどうかを確認するとよいでしょう。ループを関数でラップするだけです。そして、その価値var i=a.length;while (i--) {/*use a[i]*/}があるのは、最速のループ方法です(逆順が許容できる場合)。
ErikE 2010年

@Emtucifor:それは本当にあなたが何をしているかに依存します、そして私はそれが異なるjavascriptエンジンで異なって動作するかもしれないと思います。データでディクショナリを使用する必要がある場合は、この方法で作成することをお勧めします。dictオブジェクトが作成されると、エンジンの実装の詳細(オブジェクトのハッシュテーブルの使用)により、これはより速くなると思います。
EstebanKüber2010年

JavaScriptでは、これはdictとは呼ばれず、オブジェクトと呼ばれます
ソロモンウッコ2016年

8

これが私のものです:

String.prototype.inList=function(list){
    return (Array.apply(null, arguments).indexOf(this.toString()) != -1)
}

var x = 'abc';
if (x.inList('aaa','bbb','abc'))
    console.log('yes');
else
    console.log('no');

配列を渡しても問題がない場合、これはより高速です。

String.prototype.inList=function(list){
    return (list.indexOf(this.toString()) != -1)
}

var x = 'abc';
if (x.inList(['aaa','bbb','abc']))
    console.log('yes')

ここにjsperfがあります:http ://jsperf.com/bmcgin-inlsit


率直に言って、配列を渡す方がおそらく便利であり、おそらくArrayプロトタイプにあるはずArray.prototype.containsです。
ソロモンウッコ2016年

6

RegExp普遍的ですが、あなたは配列で作業していることを理解しています。だから、このアプローチをチェックしてください。私はそれを使用しており、それは非常に効果的で非常に高速です!

var str = 'some string with a';
var list = ['a', 'b', 'c'];
var rx = new RegExp(list.join('|'));

rx.test(str);

また、いくつかの変更を適用することもできます。

一発ギャグ

new RegExp(list.join('|')).test(str);

大文字小文字を区別しません

var rx = new RegExp(list.join('|').concat('/i'));


他にもたくさん!


正規表現を使用するには、特殊文字の束を避ける必要があります。また、あまり明確ではありません。それは良い解決策ではないと思います。
ErikE、2015年

@ErikE私はあなたの予約を理解したので、RegExpを使用しない別のコードを追加して私の答えを更新しました。IEとレトロ互換で、非常に慣用的で高速です。
sospedra 2016年

あなたの追加のコードは、あなたがRegexソリューションを投稿することを決定する5年前に私が提供した私の回答とほぼ同じです。ご参加いただきありがとうございます。同時に、以前の回答にロールバックするのが最善だと思います。
ErikE

@ErikEはい、そうです、私は質問の回答をチェックするために使用しません。そして、私はそれが本当に似ていることに同意します。
sospedra 2016年

6

indexOfの使用(IE8では機能しません)。

if (['apple', 'cherry', 'orange', 'banana'].indexOf(value) >= 0) {
    // found
}

IE8をサポートするには、MozillaのindexOfを実装できます。

if (!Array.prototype.indexOf) {
    // indexOf polyfill code here
}

String.prototype.matchによる正規表現(ドキュメント)。

if (fruit.match(/^(banana|lemon|mango|pineapple)$/)) {

}

1
ページの他の回答を正確に複製していることに気づきましたか?これは価値を追加しません。
ErikE

5

in_array関数を使用する必要があるようです。

jQuery-> inArray

プロトタイプ-> Array.indexOf

または、jQueryまたはPrototypeを使用していない場合は、以下の例を参照してください。

文体上の注意: thisthingという名前の変数は、その内容(名詞)について何かを伝えるために名前を付ける必要があります。


ああ、それらは変数ではありませんでしたが、式のランダムなプレースホルダーとして意図されていました...私がスクリプトをどのように使用するかを計画した例にすぎません。
ErikE 2010年

5

indexOf(他のポスターが示唆している)に加えて、プロトタイプのEnumerable.include()を使用すると、これをより簡潔で簡潔にすることができます

var list = ['a', 'b', 'c'];
if (list.include(str)) {
  // do stuff
}

5
Enumerable.include()は非推奨になりましたが、Array.prototype.includes()が登場し、IE(もちろん)とEdge(もちろん)を除くほとんどのブラウザーで既に動作しています。
白ひげ2016年

2

質問、およびArray.indexOfメソッドを使用した解決策をありがとう。

このソリューションのコードを使用して、IMOで書き込みを単純化し、読み取りを明確にするinList()関数を作成しました。

function inList(psString, psList) 
{
    var laList = psList.split(',');

    var i = laList.length;
    while (i--) {
        if (laList[i] === psString) return true;
    }
    return false;
}

使用法:

if (inList('Houston', 'LA,New York,Houston') {
  // THEN do something when your string is in the list
}

1
JavaScript配列リテラルはとても簡単なので、分割できるのに分割できる理由はわかりません'Houston'.inList(['LA', 'New York', 'Houston'])。おそらく、if (!String.prototype.inList) {String.prototype.inList = function(arr) {return arr.indexOf(this) >= 0};}またはあなたのwhile方法を使用します。
ErikE 2011

0

文字列とリストを取得する単純な関数について誰も言及していなかったことに驚いています。

function in_list(needle, hay)
{
    var i, len;

    for (i = 0, len = hay.length; i < len; i++)
    {
        if (hay[i] == needle) { return true; }
    }

    return false;
}

var alist = ["test"];

console.log(in_list("test", alist));

ジムは、あなたが提案したとおりに、サム、2011年8月27日1:29に。実際、選択した答えはほぼ同じで、パラメーターではなく文字列にこれを指定するだけです。
ErikE 2012

@ErikE申し訳ありませんが、ジムの答えはあなたが言ったように私には奇妙に思えました。そして、あなたの受け入れられた答えはを返します。int何人かの人々はbool戻りを探してこの質問に出くわすかもしれないので。それは少数の人々を助けるかもしれないと考えました。
サミュエルパーキンソン

0

私の解決策は次のような構文になります:

// Checking to see if var 'column' is in array ['a', 'b', 'c']

if (column.isAmong(['a', 'b', 'c']) {
  // Do something
}

これを実装するには、次のように基本的なObjectプロトタイプを拡張します。

Object.prototype.isAmong = function (MyArray){
   for (var a=0; a<MyArray.length; a++) {
      if (this === MyArray[a]) { 
          return true;
      }
   }
   return false;
}

あるいは、メソッドにisInArray(おそらくinArrayではない)または単にisInという名前を付けることもできます。

利点:シンプルでわかりやすく、自己文書化。


オブジェクトの拡張に問題がある可能性があります。「Googleマップチームはこれを難しい方法で学びました」の下にあるbolinfest.com/javascript/inheritance.phpと、ブラウザーの実装または他のユーザーのコードとの非互換性。ハッシュマップが作成されると、配列の反復処理はハッシュマップでキーを見つけるよりも遅いため、ErikEの答えが最良の答えだとまだ思います。myValues[key];ここで、myValuesはオブジェクトで、キーは任意の文字列または数値です。
HMR 2013年

-1

SLaksの回答の簡略版も機能します。

if ('abcdefghij'.indexOf(str) >= 0) {
    // Do something
}

....文字列は配列自体の一種なので。:)

必要に応じて、前に説明したようにInternet Explorerのindexof関数を実装します。


1
これは、意図されていなかった1文字の文字列でのみ機能します。
ErikE 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.