2012-11-22 12 views
15

Jaki jest najlepszy sposób sprawdzenia, czy pewna wartość znajduje się w wycinku łańcucha? Używałbym zestawu w innych językach, ale Go go nie ma.Sprawdź, czy plaster łańcuchowy zawiera określoną wartość w Go

Moja najlepsza próba jest to tak daleko:

package main 

import "fmt" 

func main() { 
    list := []string{"a", "b", "x"} 
    fmt.Println(isValueInList("b", list)) 
    fmt.Println(isValueInList("z", list)) 
} 

func isValueInList(value string, list []string) bool { 
    for _, v := range list { 
     if v == value { 
      return true 
     } 
    } 
    return false 
} 

http://play.golang.org/p/gkwMz5j09n

Rozwiązanie to powinno być ok dla małych plasterki, ale co zrobić na plasterki z wielu elementów?

Odpowiedz

37

Jeśli masz kawałek strun w dowolnej kolejności, znalezienie jeśli wartość istnieje w plaster wymaga O (n) czas. Dotyczy to wszystkich języków.

Jeśli zamierzasz wykonywać wyszukiwanie w kółko, możesz użyć innych struktur danych, aby wyszukiwanie było szybsze. Jednak budowanie tych struktur wymaga co najmniej O (n) czasu. Otrzymasz więc korzyści tylko wtedy, gdy korzystasz ze struktur danych więcej niż raz.

Na przykład można załadować łańcuchy do mapy. Wtedy wyszukiwania zajęłyby O (1) czas. Wstawki wziąć także O (1) czas podejmowania czas początkowy build odbioru O (n):

set := make(map[string]bool) 
for _, v := range list { 
    set[v] = true 
} 

fmt.Println(set["b"]) 

Można również sortować Twój kawałek ciąg, a następnie zrobić wyszukiwania binarnego. Wyszukiwania binarne występują w czasie O (log (n)). Budynek może trwać od O (n * log (n)).

sort.Strings(list) 
i := sort.SearchStrings(list, "b") 
fmt.Println(i < len(list) && list[i] == "b") 

Choć teoretycznie podano nieskończoną liczbę wartości, mapa jest szybszy, w praktyce jest to bardzo prawdopodobne, szukając uporządkowany wykaz będzie szybciej. Musisz to zrobić samemu.

4

Aby wymienić zestawy, można użyć map[string]whatever. To nie byłaby lżejsza, jaką możesz sobie wyobrazić (jest wskaźnik do wartości, której nie potrzebujesz), ale oprócz pisania własnego stołu haszowego jest to najbardziej wydajny i jest całkiem zoptymalizowany, ponieważ jest wbudowany.

set := make(map[string]uint8) 

Aby umieścić element:

set[item]=1 

Aby sprawdzić, czy dany element jest obecny:

_, ok = set[item] 

jest to wspólny idiom w Go. Jeśli ok jest prawdziwe, to element był obecny. Jeśli ok jest fałszem, element nie był obecny.

+6

Dla idiomatycznej Go użyjesz 'map [keyType] struct {}' (pusta struktura o wartości zero) lub 'map [keyType] bool' dla tego i ** nie ** uint8, jak pokazano. W pierwszym przypadku użyjesz pokazanego '_, ok: = zestawu [item]'. Jeśli używasz bool, możesz po prostu zrobić 'if set [item]' jako nieistniejące wpisy zwracają ["zero value"] (https://golang.org/ref/spec#The_zero_value), która dla bool jest fałszywa. –

2

Możesz użyć mapy i mieć wartość np. bool

m := map[string] bool {"a":true, "b":true, "x":true} 
if m["a"] { // will be false if "a" is not in the map 
    //it was in the map 
} 

Istnieje również pakiet sort, więc można sortować i wyszukiwania binarne twoje plastry

+2

Pamiętaj, że nie musisz używać wartości dumy bool. Możesz użyć pustej struktury w następujący sposób: 'map [string] struct {}'. – nemo

+3

Aby wyjaśnić, co powiedział @nemo, zaletą użycia struct {} jest brak pamięci. –

+2

"Nie ma pamięci" ... dla wartości, oczywiście mapa nadal pobiera pamięć dla kluczy i tablicy mieszającej (lub jakiejkolwiek implementacji), po prostu minimalizuje pamięć używaną przez mapę (kosztem wymagania 'jeśli _ , ok: = map ["a"]; ok "styl sprawdza raczej po prostu' if map ["a"] '). –

Powiązane problemy