2009-02-01 9 views
84

Jaki byłby najlepszy sposób wyszukiwania string[], aby zobaczyć, czy zawiera element. To był mój pierwszy strzał. Ale być może jest coś, co przeoczam. Rozmiar tablicy nie będzie większy niż 200 elementów.Czy ciąg w tablicy?

bool isStringInArray(string[] strArray, string key) 
{ 
    for (int i = 0; i <= strArray.Length - 1; i++) 
     if (strArray[i].ToString() == key) 
      return true; 
    return false; 
} 

Odpowiedz

169

Wystarczy użyć już wbudowanych w contains() metoda:

using System.Linq; 

//... 

string[] array = { "foo", "bar" }; 
if (array.Contains("foo")) { 
    //... 
} 
+0

Z jakiegoś powodu, gdy najpierw szukałem metody, nie mogłem jej znaleźć ... dzięki. – Brad

+4

@Brad: To dlatego, że jest to metoda rozszerzenia pochodząca z Enumerable. – AnthonyWJones

+47

Musisz włączyć System.Linq, aby to działało. –

1

Można również używać LINQ iteracyjne nad tablicy. lub możesz użyć metody Znajdź, która bierze delegata, aby ją wyszukać. Jednak myślę, że metoda znalezienia jest nieco droższa niż po prostu przepuszczanie.

+0

Metoda Znajdź będzie algorytmicznie identyczna z metodą" loop-through ". Dodatkowy koszt to tworzenie obiektów, a może warstwa dwukierunkowa, ale jeśli martwisz się optymalizacją tych działań kosztem czytelności, martwisz się niewłaściwymi rzeczami. –

6

Czy tablica jest posortowana? Jeśli tak, możesz zrobić binary search. Oto the .NET implementation as well. Jeśli tablica zostanie posortowana, to wyszukiwanie binarne poprawi wydajność w stosunku do dowolnego rozwiązania iteracyjnego.

+0

Cóż, O (N) do O (log n) ;-p –

+0

Usunąłem mój hiperboliczny "wykładniczo" :) –

12

Jesteś po prostu za funkcją Array.Exists (lub metodą rozszerzenia Contains, jeśli korzystasz z .NET 3.5, co jest nieco wygodniejsze).

+3

Oto działający przykład dla .NET 2.0: if (Array.Exists (arrayToLookThrough, o => o == elementToSearchFor)) – Fueled

6

Linq (na s & G)

var test = "This is the string I'm looking for"; 
var found = strArray.Any(x=>x == test); 

lub, w zależności od wymagań

var found = strArray.Any(
    x=>x.Equals(test, StringComparison.OrdinalIgnoreCase)); 
1

to szybciej niż iteracja tablicy ręcznie:

static bool isStringInArray(string[] strArray, string key) 
    { 

     if (strArray.Contains(key)) 
      return true; 
     return false; 
    } 
+1

A to szybciej? – senfo

+0

używanie LINQ jest szybsze niż powtarzanie ciągu znaków, tak jak to miało miejsce w przykładzie. strArray.Contains (key) to wszystko, co jest naprawdę potrzebne –

+2

Za kulisami, strArray.Contains (key) po prostu będzie przechodzić przez macierz, tak czy inaczej ... nie ma magii, która zmusza Cię do zrobienia O (n) Szukaj. –

2

układów jest , ogólnie, słaba struktura danych do wykorzystania, jeśli chcesz zapytać, czy dany obiekt jest w kolekcji lub nie.

Jeśli często korzystasz z tego wyszukiwania, warto użyć raczej Dictionary<string, something> niż tablicy. Wyszukiwanie w słowniku to O (1) (stały czas), podczas przeszukiwania tablicy jest O (N) (wymaga czasu proporcjonalnego do długości tablicy).

Nawet jeśli tablica zawiera tylko 200 elementów, jeśli wykonasz wiele takich wyszukiwań, słownik będzie prawdopodobnie szybszy.

+1

wyszukiwanie binarne to O (log n); słownik ** subtends ** do O (1) - ale jest dużo narzutów; w przypadku małych i średnich rozmiarów wyszukiwanie liniowe lub wyszukiwanie binarne może być skuteczniejsze. –

1

Jak wspomniano wiele razy w powyższym wątku, jest to zależne od używanej struktury. .Net Framework 3 i wyżej ma metody .Contains() lub Exists() dla tablic. Dla innych ram poniżej, można wykonać następujące sztuczkę zamiast zapętlenie za pośrednictwem tablicy ...

((IList<string>)"Your String Array Here").Contains("Your Search String Here") 

Niezbyt pewny na wydajność ... Dave

20

wiem, że to jest stary, ale chciałem nowy czytelników, aby wiedzieć, że istnieje nowa metoda, aby to zrobić przy użyciu metod generycznych i rozszerzeń.

Możesz przeczytać mój blog post aby zobaczyć więcej informacji o tym, jak to zrobić, ale główna idea jest taka:

Dodając tę ​​metodę rozszerzenia do kodu:

public static bool IsIn<T>(this T source, params T[] values) 
{ 
    return values.Contains(source); 
} 

możesz wykonywać szukaj tak:

string myStr = "str3"; 
bool found = myStr.IsIn("str1", "str2", "str3", "str4"); 

Działa na każdym typie (o ile tworzy się dobrą metodę równości). Dowolny typ wartości na pewno.

+0

Mam coś takiego: 'var xxx = csvData.Rows [0] .ItemArray [0] .IsIn (". 00 "," 0.0 "," .25 "," 0.5 "," .5 ",". 50 "," .75 ");' co chcę zrobić, to przejrzeć, który moduł danych w pierwszej kolumnie, aby sprawdzić, czy wartości nie kończą się żadnym z następujących łańcuchów. Jeśli nie, to chcę Zwróć ciąg znaków stwierdzający, że brakuje wartości ".00" na przykład używając twojego przykładu Nie mogę sprawić, żeby ten zadziałał, jest to trochę trudniejsze, ponieważ nie chcę zwrócić boola Zmieniłem twoją metodę, aby zwrócić ciąg znaków ale nadal nie działa żadnych sugestii. – MethodMan

+0

Wydaje się, że jest to lepsze pytanie na stronie. Dalej, w razie potrzeby podaj tę odpowiedź. –

+0

Byłem w stanie wymyślić niesamowity sposób robienia tego, co chciałem zrobić Napisałem coś, co sprawdzi, czy wartości ciągu wewnątrz pętli for dla Datatables ItemArray, kończą się jedną z poniższych wartości, które miałem w mój ciąg znaków 'public static bool EndWithValue (ta wartość ciągu, IEnumerable wartości) { zwraca wartości. Any (item => value.EndsWith (item)); } ' – MethodMan

Powiązane problemy