Sprawdź, czy wartość znajduje się w tablicy (C #)

109

Jak sprawdzić, czy wartość znajduje się w tablicy w języku C #?

Na przykład chcę utworzyć tablicę z listą nazw drukarek.

Zostaną one przekazane do metody, która przyjrzy się każdemu ciągowi po kolei, a jeśli ciąg jest taki sam jak wartość w tablicy, wykonaj tę czynność.

Na przykład:

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

To są nazwy drukarek, które są podawane do metody PrinterSetup.

PrinterSetup będzie wyglądać mniej więcej tak (jakiś pseudokod):

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

Jak sformatować if (printer == "jupiter")w sposób, który C # może rozpoznać?

Cecil Rodriguez
źródło
4
Spróbuj nadać nazwie parametru typ (ciąg znaków) i wszystko będzie dobrze.
Jon Skeet
2
Jestem trochę zdezorientowany jako pytanie. Czy pytasz, jak sprawdzić, czy wartość znajduje się w tablicy, lub jak zrobić porównanie ciągów w C #? Jeśli to drugie, użyjesz printer.Equals("jupiter"). Jeśli to pierwsza, użyj linqiprinter.Contains("jupiter")
newfurniturey
@newfurniturey Całkiem tak ... pytanie jest zdezorientowane, przykładowy kod nie pasuje do tytułu, a zatem odpowiedzi są również niejasne; dlaczego takie bzdury cieszą się uznaniem, jest poza mną. I nie ma potrzeby printer.Equals("jupiter")... Kod OP if (printer == "jupiter")działa dobrze ... o ile printerjest zadeklarowany jako ciąg, jak zauważa Skeet.
Jim Balter

Odpowiedzi:

232

Dodaj niezbędną przestrzeń nazw

using System.Linq;

Następnie możesz użyć Contains()metody linq

string[] printer = {"jupiter", "neptune", "pangea", "mercury", "sonic"};
if(printer.Contains("jupiter"))
{
    Process.Start("BLAH BLAH CODE TO ADD PRINTER VIA WINDOWS EXEC"");
}
Dmytro
źródło
2
@ 0A0D. Ta odpowiedź brzmi: uważam, że najlepszym sposobem jest najprostszy / najkrótszy i dobrze znany sposób osiągnięcia tego samego ( How do I check if a value is in an array in C#?), a także skuteczny. Bez pętli bez dodatkowej metody. Tylko przestrzeń nazw jest dodatkowa, co nie jest wielką rzeczą.
Sami
6
@Sami: Linq wewnętrznie używa pętli.
2
@ 0A0D Sam prawdopodobnie odnosi się do napisanego kodu, a nie skompilowanych instrukcji. Linq używa pętli i metod wewnętrznie, ale z punktu widzenia programistów wszystko to jest ukryte i nie trzeba się tym martwić.
Trisped
1
Prawo @ 0A0D. Chodziło mi o to, że koder / programista nie musiał wykonywać prawej pętli. Oczywiście sprawdzenie z tablicy wymaga pętli :)
Sami
3
Z pewnością jest to łatwe i godne polecenia. Jeśli nie masz dostępu do Linq lub nie chcesz używać Linq, możesz polegać na jawnej implementacji interfejsu tablicy. Od .NET 1.1 mamy ((IList)printer).Contains("Jupiter")nieogólne (może zawierać typy wartości itp.) I działa nawet dla tablic wielowymiarowych. A od .NET 2.0 mamy bardziej magiczny, ((IList<string>)printer).Contains("Jupiter")który jest bardziej bezpieczny dla typów. Podejście Linq było nowością w .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) Prawda 2) Fałsz 3) Prawda 4) Fałsz


źródło
6
To powinna być akceptowana odpowiedź. Jeśli używasz macierzy, nie jest to całkowicie nieprawdopodobne, że wydajność ma znaczenie. W takim przypadku Linq jest często złym wyborem.
Philm
22
if ((new [] {"foo", "bar", "baaz"}).Contains("bar"))
{

}  
Gość
źródło
To jest ogólny przykład - czy możesz podać taki, który lepiej pasuje do pytania?
kaz
9
Może to być ogólny przykład, ale właśnie tego szukałem.
Grant Birchmeier
7

Coś takiego?

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"");
    }
}
code4life
źródło
7
    public static bool Contains(Array a, object val)
    {
        return Array.IndexOf(a, val) != -1;
    }
Raz Megrelidze
źródło
2
Lubię to. Jednak zakończy się niepowodzeniem, jeśli ajest to tablica wielowymiarowa ( new string[10, 20, 15]na przykład), z wyjątkiem. Nie powiedzie się również w przypadku tablic jednowymiarowych, które nie są indeksowane od zera (na przykład Array.CreateInstance(typeof(string), new[] { 5, }, new[] { -2, })rzadkie w C #, przyznaję), z prawdopodobnie nieprawidłową wartością zwracaną. Te niedociągnięcia można łatwo naprawić za pomocą leków generycznych:public static bool Contains<TElement>(TElement[] a, TElement val) { return Array.IndexOf(a, val) != -1; }
Jeppe Stig Nielsen
I tak, ale tylko dlatego, że jest bez Linq i potwierdza, że IndexOf jest jedyną rzeczą, w lewo do użytku.
Bitterblue
6

Uwaga: pytanie dotyczy tablic ciągów. Wymienionych procedur nie należy mieszać z metodą .Contains dla pojedynczych ciągów.

Chciałbym dodać rozszerzającą odpowiedź odnoszącą się do różnych wersji C # iz dwóch powodów:

  • Przyjęta odpowiedź wymaga Linq, który jest doskonale idiomatycznym C #, ale nie przychodzi bez kosztów i nie jest dostępny w C # 2.0 lub niższym. W przypadku tablic wydajność może mieć znaczenie, więc są sytuacje, w których chcesz pozostać przy metodach Array.

  • Żadna odpowiedź nie odnosi się bezpośrednio do pytania, w którym poproszono również o umieszczenie tego w funkcji (ponieważ niektóre odpowiedzi są również mieszaniem łańcuchów z tablicami ciągów, nie jest to całkowicie nieważne).

Array.Exists () to metoda C # / .NET 2.0 i nie wymaga Linq. Wyszukiwanie w tablicach to O (n). Aby uzyskać jeszcze szybszy dostęp, użyj HashSet lub podobnych kolekcji.

Od .NET 3.5 istnieje również metoda ogólna 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");
   }
}

Możesz napisać własną metodę rozszerzenia (C # 3.0 i nowsze), aby dodać cukier składniowy, aby uzyskać takie same / podobne „.Contains”, jak w przypadku ciągów znaków dla wszystkich tablic bez uwzględniania 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));
}

W tym przypadku ArrayContains()używana jest ta metoda, a nie metoda Contains z Linq.

Wspomniane gdzie indziej .Contains metody odwołują się do List<T>.Contains(od C # 2,0) lub ArrayList.Contains(od C # 1.1), ale nie bezpośrednio do tablic.

Philm
źródło
1
Proponuję zmienić nazwę na ArrayContains (), aby uniknąć pomyłki z Linq Contains ()
peter.cyc
Zrobiłem to, chociaż istnieją również argumenty przeciw: podstawową ideą polimorfizmu jest używanie tej samej nazwy dla różnych typów danych, zwłaszcza mając na uwadze ustawienie Linq. Używanie różnych nazw nie jest polimorficzne. Ale myślę, że zwyciężą czytelność i unikanie nieporozumień, więc tak.
Philm
4

Po prostu brakuje Ci czegoś w Twojej metodzie:

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

Po prostu dodaj stringi wszystko będzie dobrze.


źródło
3

Nie bardzo jasne, na czym polega Twój problem, ale wygląda na to, że chcesz czegoś takiego:

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

    if( printer.Exists( p => p.Equals( "jupiter" ) ) )
    {
        ...
    }
Brandon Moretz
źródło
2

Rozważ użycie HashSet<T>Class ze względu na wydajność wyszukiwania:

Ta metoda jest operacją O (1).

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

Na przykład:

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");
        }
        // ...
    }
}
Sergey Brunov
źródło
1

Przeszukałem teraz ponad 2 godziny, aby znaleźć fajny sposób, jak znaleźć duplikaty na liście i jak je usunąć . Oto najprostsza odpowiedź:

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

Wynik będzie wyglądał następująco: Zduplikowane elementy zostaną usunięte z nowej listy o nazwie odrębne!

Ricardo Fercher
źródło