Controlla se un valore è in una matrice (C #)


109

Come posso verificare se un valore è in una matrice in C #?

Ad esempio, voglio creare un array con un elenco di nomi di stampanti.

Questi verranno inviati a un metodo, che esaminerà ciascuna stringa a turno e, se la stringa è uguale a un valore in un array, eseguire tale azione.

Per esempio:

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

Questi sono i nomi delle stampanti, vengono inviati al metodo PrinterSetup.

PrinterSetup avrà un aspetto simile a questo (alcuni pseudocodici):

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

Come faccio a formattare if (printer == "jupiter")in modo che C # possa riconoscere?


4
Prova a dare al nome del parametro un tipo (stringa) e andrà bene.
Jon Skeet

2
Sono un po 'confuso come la domanda. Stai chiedendo come verificare se un valore è in un array o come eseguire il confronto tra stringhe in C #? Se è quest'ultimo, useresti printer.Equals("jupiter"). Se è il primo, usa linqeprinter.Contains("jupiter")
newfurniturey

@newfurniturey Proprio così ... la domanda è confusa, il codice di esempio non corrisponde al titolo, e quindi anche le risposte sono confuse; perché una schifezza come questa viene votata è al di là di me. E non c'è bisogno di farlo printer.Equals("jupiter")... Il codice dell'OP if (printer == "jupiter")funziona perfettamente ... fintanto che printerviene dichiarato essere una stringa, come osserva Skeet.
Jim Balter

Risposte:


231

Aggiungi lo spazio dei nomi necessario

using System.Linq;

Quindi puoi usare il Contains()metodo linq

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

2
@ 0A0D. Questa risposta è, credo, la migliore come il modo più semplice / breve e ben noto per ottenere la stessa cosa ( How do I check if a value is in an array in C#?) ed anche efficiente. Nessun ciclo, nessun metodo aggiuntivo. Solo uno spazio dei nomi è extra che non è una grande cosa.
Sami

6
@ Sami: Linq utilizza i loop internamente.

2
@ 0A0D Sam si riferisce probabilmente a codice scritto, non a istruzioni compilate. Linq utilizza internamente cicli e metodi, ma dal punto di vista dei programmatori tutto ciò è nascosto e non deve essere preoccupato.
Trisped

1
Destra @ 0A0D. Volevo dire che il programmatore / sviluppatore non aveva bisogno di eseguire il loop corretto. Il controllo fuori rotta dall'array necessita di un ciclo :)
Sami

3
Questo è certamente facile e raccomandabile. Se non si ha accesso a Linq o non si desidera utilizzare Linq, è possibile fare affidamento su alcune esplicite implementazioni dell'interfaccia dell'array. A partire da .NET 1.1 abbiamo ((IList)printer).Contains("Jupiter")che non è generico (può contenere tipi di valore ecc.) E funziona anche per array multidimensionali. E da .NET 2.0 abbiamo il più magico ((IList<string>)printer).Contains("Jupiter")che è più sicuro per i tipi. L'approccio Linq era nuovo in .NET 3.5.
Jeppe Stig Nielsen

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) Vero 2) Falso 3) Vero 4) Falso


6
Questa dovrebbe essere la risposta accettata. Se si utilizza un array, non è del tutto improbabile che le prestazioni contino. In questo caso, Linq è spesso la scelta sbagliata.
Philm

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

}  

Questo è un esempio generale: puoi fornirne uno che corrisponda meglio alla domanda?
kaz

9
Può essere un esempio generale, ma è esattamente quello che stavo cercando.
Grant Birchmeier

7

Qualcosa come questo?

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
Mi piace questo. Tuttavia, fallirà se aè un array multidimensionale (come new string[10, 20, 15]ad esempio), con un'eccezione. Fallirà anche con array unidimensionali che non sono indicizzati da zero (ad esempio Array.CreateInstance(typeof(string), new[] { 5, }, new[] { -2, }), raro in C # lo ammetto), con un valore restituito forse errato. Queste carenze sono facili da correggere con i generici:public static bool Contains<TElement>(TElement[] a, TElement val) { return Array.IndexOf(a, val) != -1; }
Jeppe Stig Nielsen

Mi piace, ma solo perché è senza Linq e conferma che IndexOf è l'unica cosa rimasta da usare.
Bitterblue

6

Nota: la domanda riguarda gli array di stringhe. Le routine menzionate non devono essere mescolate con il metodo .Contains di singole stringhe.

Vorrei aggiungere una risposta estesa che fa riferimento a diverse versioni C # e per due motivi:

  • La risposta accettata richiede Linq che è perfettamente idiomatico C # mentre non è senza costi e non è disponibile in C # 2.0 o inferiore. Quando è coinvolto un array, le prestazioni possono essere importanti, quindi ci sono situazioni in cui si desidera rimanere con i metodi Array.

  • Nessuna risposta risponde direttamente alla domanda in cui è stato chiesto anche di mettere questo in una funzione (poiché alcune risposte stanno anche mescolando stringhe con array di stringhe, questo non è del tutto irrilevante).

Array.Exists () è un metodo C # /. NET 2.0 e non necessita di Linq. La ricerca negli array è O (n). Per un accesso ancora più veloce usa HashSet o raccolte simili.

A partire da .NET 3.5 esiste anche un metodo generico 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");
   }
}

È possibile scrivere un metodo di estensione personalizzato (C # 3.0 e versioni successive) per aggiungere lo zucchero sintattico per ottenere lo stesso / simile ".Contains" delle stringhe per tutti gli array senza includere 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));
}

In questo caso ArrayContains()viene utilizzato questo metodo e non il metodo Contains di Linq.

I metodi .Contains menzionati altrove fanno riferimento a List<T>.Contains(da C # 2.0) o ArrayList.Contains(a partire da C # 1.1), ma non direttamente agli array.


1
Suggerisco di cambiare il nome in ArrayContains () per evitare confusione con Linq Contains ()
peter.cyc

L'ho fatto, anche se ci sono anche argomenti contro: l'idea di base del polimorfismo è usare lo stesso nome per diversi tipi di dati, specialmente con un'impostazione di Linq in mente. Usare nomi diversi non è polimorfo. Ma la leggibilità e l'evitare incomprensioni vinceranno, credo, quindi sì.
Philm

4

Ti manca solo qualcosa nel tuo metodo:

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

Basta aggiungere stringe starai bene.


3

Non è molto chiaro quale sia il tuo problema, ma sembra che tu voglia qualcosa del genere:

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

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

2

Prendi in considerazione l'utilizzo di HashSet<T>Class per motivi di prestazioni di ricerca:

Questo metodo è un'operazione O (1).

- HashSet<T>.ContainsMetodo (T), MSDN .

Per esempio:

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

Ho cercato ora più di 2 ore per trovare un modo carino su come trovare i duplicati in un elenco e su come rimuoverli . Ecco la risposta più semplice:

//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();

L'output sarà simile a questo: gli elementi duplicati verranno rimossi nel nuovo elenco chiamato distinto!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.