値が配列内にあるかどうかを確認します(C#)


109

値がC#の配列にあるかどうかを確認するにはどうすればよいですか?

同様に、プリンター名のリストを含む配列を作成したいと思います。

これらはメソッドにフィードされ、各文字列を順番に調べ、文字列が配列の値と同じである場合は、そのアクションを実行します。

例えば:

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
foreach (p in printer)
{
   PrinterSetup(p);     
}

これらはプリンターの名前で、PrinterSetupメソッドに渡されます。

PrinterSetupは次のようになります(いくつかの疑似コード)。

public void PrinterSetup(printer)
{
   if (printer == "jupiter") 
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC");
   }
}

if (printer == "jupiter")C#が認識できる形式にするにはどうすればよいですか?


4
パラメータ名にタイプ(文字列)を付けてみてください。問題はありません。
ジョン・スキート

2
質問としてはちょっと混乱しています。値が配列にあるかどうかを確認する方法、またはC#で文字列比較を行う方法を尋ねていますか?後者の場合は、を使用しますprinter.Equals("jupiter")。前者の場合はlinq、andを使用printer.Contains("jupiter")
newfurniturey

@newfurnitureyなるほど…質問が混乱し、サンプルコードがタイトルと一致しないため、回答も同様に混乱しています。このようなくだらないことが賛成される理由は私を超えています。そして、する必要はありませんprinter.Equals("jupiter")... OPのコードは、スキートが指摘しているように、文字列であると宣言さif (printer == "jupiter")れている限り、うまく機能しprinterます。
ジムバルター2016年

回答:


231

必要な名前空間を追加する

using System.Linq;

次に、linq Contains()メソッドを使用できます

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
if(printer.Contains("jupiter"))
{
    Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
}

2
@ 0A0D。この答えは、同じこと(How do I check if a value is in an array in C#?)と効率を達成するための最も単純で最も短い、よく知られている方法として、最善の方法だと思います。ループなし、余分なメソッドなし。名前空間だけは余分なもので、大きなことではありません。
サミ

6
@Sami:Linqは内部的にループを使用します。

2
@ 0A0Dサムはおそらくコンパイルされた命令ではなく、書かれたコードを参照しています。Linqは内部的にループとメソッドを使用しますが、コーダーの観点からは、すべてのことは隠されており、心配する必要はありません。
12

1
正しい@ 0A0D。私はコーダー/開発者が正しいループをする必要がないことを意味しました。配列からのオフコースチェックにはループが必要です:)
Sami

3
これは確かに簡単でお勧めです。Linqにアクセスできない場合、またはLinqを使用したくない場合は、配列の明示的なインターフェイス実装を利用できます。.NET 1.1以降((IList)printer).Contains("Jupiter")は、ジェネリックではなく(値の型などを囲んでもよい)、多次元配列でも機能する。そして.NET 2.0以降((IList<string>)printer).Contains("Jupiter")では、よりタイプセーフな、より魔法のようになっています。Linqアプローチは.NET 3.5で新しく導入されました。
Jeppe Stig Nielsen 2016

29
   string[] array = { "cat", "dot", "perls" };

// Use Array.Exists in different ways.
bool a = Array.Exists(array, element => element == "perls");
bool b = Array.Exists(array, element => element == "python");
bool c = Array.Exists(array, element => element.StartsWith("d"));
bool d = Array.Exists(array, element => element.StartsWith("x"));

// Display bools.
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
Console.WriteLine(d);
----------------------------output-----------------------------------

1)真2)偽3)真4)偽


6
これは受け入れられる答えになるはずです。配列を使用する場合、その可能性はまったくありませんが、そのパフォーマンスは重要です。この場合、Linqはしばしば間違った選択です。
Philm

22
if ((new [] {"foo", "bar", "baaz"}).Contains("bar"))
{

}  

これは一般的な例です-質問によく一致するものを提供できますか?
kaz

9
それは一般的な例かもしれませんが、まさに私が探していたものです。
Grant Birchmeier

7

このようなもの?

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
PrinterSetup(printer);

// redefine PrinterSetup this way:
public void PrinterSetup(string[] printer)
{
    foreach (p in printer.Where(c => c == "jupiter"))
    {
        Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
    }
}

7
    public static bool Contains(Array a, object val)
    {
        return Array.IndexOf(a, val) != -1;
    }

2
私はこれが好き。ただし、a多次元配列(new string[10, 20, 15]たとえば)の場合、例外が発生して失敗します。また、ゼロからインデックスが付けられていない1次元配列(Array.CreateInstance(typeof(string), new[] { 5, }, new[] { -2, })C#では認められることはまれですが、など)でも失敗し、戻り値が誤っている可能性があります。これらの欠点は、ジェネリックで固定するのは簡単です:public static bool Contains<TElement>(TElement[] a, TElement val) { return Array.IndexOf(a, val) != -1; }
ジャップスティグ・ニールセン

このような私が、それはLINQのなしだと、それはIndexOfメソッドが唯一のものであることを確認しただけであるため使用。
ビターブルー

6

注:問題は文字列の配列についてです。上記のルーチンは、単一の文字列の.Containsメソッドと混合しないでください。

さまざまなC#バージョンを参照する2つの理由から、拡張された回答を追加したいと思います。

  • 受け入れられた答えは、完全に慣用的なC#であるLinqを必要としますが、コストがかからず、C#2.0以下では利用できません。配列が関係する場合、パフォーマンスが重要になる可能性があるため、Arrayメソッドを使い続けたい場合があります。

  • これを関数に入れることも求められた質問には直接回答がありません(一部の回答は文字列と文字列の配列を混合しているため、これは完全に重要ではありません)。

Array.Exists()はC#/。NET 2.0メソッドであり、Linqを必要としません。配列の検索はO(n)です。さらに高速にアクセスするには、HashSetまたは同様のコレクションを使用します。

.NET 3.5以降、ジェネリックメソッドも存在しますArray<T>.Exists()

public void PrinterSetup(string[] printer)
{
   if (Array.Exists(printer, x => x == "jupiter"))
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC");
   }
}

独自の拡張メソッド(C#3.0以上)を記述して、Linqを含まないすべての配列の文字列と同じ/類似の「。

// Using the generic extension method below as requested.
public void PrinterSetup(string[] printer)
{
   if (printer.ArrayContains("jupiter"))
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC");
   }
}

public static bool ArrayContains<T>(this T[] thisArray, T searchElement)
{
   // If you want this to find "null" values, you could change the code here
   return Array.Exists<T>(thisArray, x => x.Equals(searchElement));
}

この場合、このArrayContains()メソッドが使用され、LinqのContainsメソッドは使用されません。

他で言及されている.ContainsメソッドはList<T>.Contains(C#2.0以降)またはArrayList.Contains(C#1.1以降)を参照しますが、配列自体を直接参照しません。


1
Linq Contains()との混乱を避けるために、名前をArrayContains()に変更することをお勧めします
peter.cyc

私はこれを行いましたが、反対の意見もあります。特に、Linq設定を念頭に置いて、さまざまなデータ型に同じ名前を使用することはポリモーフィズムの基本的な考え方です。異なる名前を使用することは多態的ではありません。しかし、読みやすさと誤解の回避が勝つと私は思うので、そうです。
Philm

4

あなたはあなたのメソッドに何かが足りないだけです:

public void PrinterSetup(string printer)
{
   if (printer == "jupiter") 
   {
      Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
   }
}

追加するだけstringで大丈夫です。


3

問題はあまり明確ではありませんが、次のようなものが必要なようです。

    List<string> printer = new List<string>( new [] { "jupiter", "neptune", "pangea", "mercury", "sonic" } );

    if( printer.Exists( p => p.Equals( "jupiter" ) ) )
    {
        ...
    }

2

検索パフォーマンスのためにHashSet<T>クラスの使用を検討してください:

このメソッドはO(1)操作です。

HashSet<T>.Containsメソッド(T)、MSDN

例えば:

class PrinterInstaller
{
    private static readonly HashSet<string> PrinterNames = new HashSet<string>
        {
            "jupiter", "neptune", "pangea", "mercury", "sonic"
        };

    public void Setup(string printerName)
    {
        if (!PrinterNames.Contains(printerName))
        {
            throw new ArgumentException("Unknown printer name", "printerName");
        }
        // ...
    }
}

1

私は2時間以上かけて検索を行い、リスト内の重複を見つける方法とそれらを削除する方法を見つけました。これが最も簡単な答えです:

//Copy the string array with the filtered data of the analytics db into an list
// a list should be easier to use
List<string> list_filtered_data = new List<string>(analytics_db_filtered_data);

// Get distinct elements and convert into a list again.
List<string> distinct = list_filtered_data.Distinct().ToList();

出力は次のようになります。重複する要素は、distinctという新しいリストから削除されます。

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