web-dev-qa-db-ja.com

複数の値に一致するステートメント

このif文を書く簡単な方法はありますか?

if (value==1 || value==2)

たとえば、SQLでは、where value=1 or value=2の代わりにwhere value in (1,2)と言うことができます。

文字列、整数など、あらゆる基本的なタイプで機能するものを探しています。

70
Ricky

どうですか:

if (new[] {1, 2}.Contains(value))

しかし、それはハックです:)

または、独自の拡張メソッドを作成してもかまわない場合は、次を作成できます。

public static bool In<T>(this T obj, params T[] args)
{
    return args.Contains(obj);
}

そして、次のように使用できます。

if (1.In(1, 2))

:)

121
Amry

SQLの「IN」をエミュレートするより複雑な方法:):

public static class Ext {    
    public static bool In<T>(this T t,params T[] values){
        foreach (T value in values) {
            if (t.Equals(value)) {
                return true;
            }
        }
        return false;
    }
}

if (value.In(1,2)) {
    // ...
}

しかし、標準的な方法を使用すると、読みやすくなります。

EDIT:@Kobiの提案によると、より良い解決策:

public static class Ext {    
    public static bool In<T>(this T t,params T[] values){
        return values.Contains(t);
    }
}
35
Paolo Tedesco

これはあなたが探しているものですか?

if (new int[] { 1, 2, 3, 4, 5 }.Contains(value))
24
Homam

または、将来1または2以外の値をテストするためにswitchステートメントを使用する場合、これにより柔軟性が高まります。

switch(value)
{
case 1:
case 2:
   return true;
default:
   return false
}
6
jules

Listがある場合、既存のものを探しているだけなら(whereなど)、. Contains(yourObject)を使用できます。それ以外の場合は、Linq .Any()拡張メソッドを見てください。

6
Nik

Linqを使用して、

if(new int[] {1, 2}.Contains(value))

しかし、元のifの方が速いと思う必要があります。

5
Joel Rondeau

値の固定リストの値を長いリストで何度も検索する場合は、HashSet <T>を使用する必要があります。リストが非常に短い場合(<〜20アイテム)、このテストに基づいて、リストのパフォーマンスが向上する可能性があります HashSetとリストのパフォーマンス

HashSet<int> nums = new HashSet<int> { 1, 2, 3, 4, 5 };
// ....
if (nums.Contains(value))
5
detale

通常、いいえ。

はい、リストがArrayまたはListにある場合がありますが、それは一般的なケースではありません。

3
Steven Sudit

このような拡張メソッドはそれを行うでしょう...

public static bool In<T>(this T item, params T[] items)
{
    return items.Contains(item);
}

次のように使用します。

Console.WriteLine(1.In(1,2,3));
Console.WriteLine("a".In("a", "b"));
2
Allrameest

拡張メソッドの使用:

public static class ObjectExtension
{
    public static bool In(this object obj, params object[] objects)
    {
        if (objects == null || obj == null)
            return false;
        object found = objects.FirstOrDefault(o => o.GetType().Equals(obj.GetType()) && o.Equals(obj));
        return (found != null);
    }
}

これで次のことができます。

string role= "Admin";
if (role.In("Admin", "Director"))
{ 
    ...
} 
1
goenning

より簡単なのは主観的ですが、switchステートメントの方が簡単でしょうか?変数を繰り返す必要がないので、より多くの値を行に収めることができ、多くの比較がある行は、ifステートメントを使用する対応する行よりも読みやすくなります。

1
Tim

Vb.netまたはC#では、変数を合理的な数の別々の名前のオブジェクトと比較する最も速い一般的なアプローチ(たとえばコレクション内のすべてのものとは対照的に)は、各オブジェクトを単純に比較することですあなたがやったように。コレクションのインスタンスを作成してオブジェクトを含むかどうかを確認することは確かに可能であり、そうすることはオブジェクトをすべてのアイテムと個別に比較するよりも表現力がありますが、コンパイラが明示的に認識できる構成を使用しない限り、そのようなコードほぼ確実に、個々の比較を行うよりもはるかに遅くなります。コードの性質上、1秒あたり最大で数百回実行される場合、速度については心配しませんが、コードが元の意図よりもはるかに頻繁に実行されるものに再利用されることに注意してください。

別のアプローチは、変数が列挙型のようなものである場合、2のべき乗の列挙値を選択してビットマスクの使用を許可することです。列挙型の有効な値が32個以下の場合(たとえば、Harry = 1、Ron = 2、Hermione = 4、Ginny = 8、Neville = 16を開始)、それらを整数に格納し、一度に複数のビットを一度にチェックできますoperation((if((thisOne&(Harry | Ron | Neville | Beatrix))!= 0)/ *何かをする* /。これにより高速コードが可能になりますが、値の数が少ない列挙に制限されます。

もう少し強力なアプローチですが、注意して使用する必要があるアプローチは、値の一部のビットを使用して何かの属性を示し、他のビットはアイテムを識別することです。たとえば、ビット30はキャラクターが男性であることを示し、ビット29は友人のハリーなどを示し、下位のビットはキャラクターを区別します。このアプローチにより、ハリーの友をチェックするコードを変更することなく、ハリーの友であってもなくてもよいキャラクターを追加することができます。これを行う際の注意点の1つは、列挙値を設定するために使用される列挙定数と、それをテストするために使用される列挙定数を区別する必要があるということです。たとえば、ハリーを示す変数を設定するには、0x60000001に設定しますが、変数ISハリーかどうかを確認するには、0x00000001でビットテストする必要があります。

可能性のある値の総数が中程度(たとえば、16〜16,000程度)の場合に役立つもう1つのアプローチは、各値に関連付けられたフラグの配列を持つことです。 「if(((characterAttributes [theCharacter]&chracterAttribute.Male)!= 0)」のようなコードを作成できます。このアプローチは、文字数がかなり少ない場合に最適です。配列が大きすぎると、キャッシュミスが遅くなることがあります少数の文字を個別にテストする方が高速になるまでコードをダウンします。

1
supercat
public static bool EqualsAny<T>(IEquatable<T> value, params T[] possibleMatches) {
    foreach (T t in possibleMatches) {
        if (value.Equals(t))
            return true;
    }
    return false;
}
public static bool EqualsAny<T>(IEquatable<T> value, IEnumerable<T> possibleMatches) {
    foreach (T t in possibleMatches) {
        if (value.Equals(t))
            return true;
    }
    return false;
}
0
JWL_

私は同じ問題を抱えていましたが、switchステートメントswitch(スイッチを入れている値)でそれを解決しました{ケース1:発生させたいコード;ケース2:発生させたいコード。デフォルト:値を返す}

0
Ernest Mushinge