490 Stimmen

Hat Go eine "wenn x in" Konstruktion, ähnlich wie Python?

Wie kann ich überprüfen, ob x in einem Array ohne über das gesamte Array zu iterieren, mit Go vorhanden ist? Hat die Sprache dafür eine Konstruktion?

Wie in Python:

if "x" in array: 
  # mache etwas

558voto

andybalholm Punkte 14955

Es gibt in Go keinen integrierten Operator, um dies zu tun. Sie müssen über das Array iterieren. Sie können Ihre eigene Funktion schreiben, um dies zu tun, wie folgt:

func stringInSlice(a string, list []string) bool {
    for _, b := range list {
        if b == a {
            return true
        }
    }
    return false
}

Oder in Go 1.18 oder neuer können Sie slices.Contains (von golang.org/x/exp/slices) verwenden.

Wenn Sie die Mitgliedschaft überprüfen möchten, ohne über die ganze Liste zu iterieren, müssen Sie anstelle eines Arrays oder Slices eine Map verwenden, wie folgt:

visitedURL := map[string]bool {
    "http://www.google.com": true,
    "https://paypal.com": true,
}
if visitedURL[thisSite] {
    fmt.Println("Schon hier gewesen.")
}

169voto

sebest Punkte 2089

Another solution if the list contains static values.

z. B.: Überprüfung auf einen gültigen Wert aus einer Liste gültiger Werte:

func IsValidCategory(category string) bool {
    switch category {
    case
        "auto",
        "news",
        "sport",
        "music":
        return true
    }
    return false
}

59voto

AlexTT Punkte 903

Dies ist ein Zitat aus dem Buch "Programming in Go: Creating Applications for the 21st Century":

Die Verwendung eines einfachen linearen Suchalgorithmus ist die einzige Option für unsortierte Daten und eignet sich gut für kleine Slices (bis zu Hunderten von Elementen). Für größere Slices ist der lineare Suchalgorithmus jedoch sehr ineffizient, da im Durchschnitt jedes Mal die Hälfte der Elemente verglichen werden müssen.

Go bietet eine sort.Search() Methode, die den binären Suchalgorithmus verwendet: Dies erfordert jedes Mal nur einen Vergleich von log2(n) Elementen (wobei n die Anzahl der Elemente ist). Zum Vergleich: Eine lineare Suche von 1000000 Elementen erfordert im Durchschnitt 500000 Vergleiche und im schlimmsten Fall 1000000 Vergleiche; eine binäre Suche benötigt maximal 20 Vergleiche, selbst im schlimmsten Fall.

files := []string{"Test.conf", "util.go", "Makefile", "misc.go", "main.go"}
target := "Makefile"
sort.Strings(files)
i := sort.Search(len(files),
    func(i int) bool { return files[i] >= target })
if i < len(files) && files[i] == target {
    fmt.Printf("found \"%s\" at files[%d]\n", files[i], i)
}

https://play.golang.org/p/UIndYQ8FeW

46voto

Igor Punkte 459

Nur hatte eine ähnliche Frage und beschloss, einige der Vorschläge in diesem Thread auszuprobieren.

Ich habe die besten und schlechtesten Szenarien von 3 Arten von Suchvorgängen getestet:

  • mit einer Map
  • mit einer Liste
  • mit einer Switch-Anweisung

Hier ist der Funktionscode:

func belongsToMap(lookup string) bool {
list := map[string]bool{
    "900898296857": true,
    "900898302052": true,
    "900898296492": true,
    "900898296850": true,
    "900898296703": true,
    "900898296633": true,
    "900898296613": true,
    "900898296615": true,
    "900898296620": true,
    "900898296636": true,
}
if _, ok := list[lookup]; ok {
    return true
} else {
    return false
}
}

func belongsToList(lookup string) bool {
list := []string{
    "900898296857",
    "900898302052",
    "900898296492",
    "900898296850",
    "900898296703",
    "900898296633",
    "900898296613",
    "900898296615",
    "900898296620",
    "900898296636",
}
for _, val := range list {
    if val == lookup {
        return true
    }
}
return false
}

func belongsToSwitch(lookup string) bool {
switch lookup {
case
    "900898296857",
    "900898302052",
    "900898296492",
    "900898296850",
    "900898296703",
    "900898296633",
    "900898296613",
    "900898296615",
    "900898296620",
    "900898296636":
    return true
}
return false
}

Best-case Szenarien wählen das erste Element in Listen aus, Worst-case-Szenarien verwenden einen nicht vorhandenen Wert.

Hier sind die Ergebnisse:

BenchmarkBelongsToMapWorstCase-4         2000000           787 ns/op
BenchmarkBelongsToSwitchWorstCase-4     2000000000           0.35 ns/op
BenchmarkBelongsToListWorstCase-4       100000000           14.7 ns/op
BenchmarkBelongsToMapBestCase-4          2000000           683 ns/op
BenchmarkBelongsToSwitchBestCase-4      100000000           10.6 ns/op
BenchmarkBelongsToListBestCase-4        100000000           10.4 ns/op

Die Switch-Anweisung gewinnt in allen Fällen, der Worst Case ist überraschenderweise schneller als der Best Case.

Maps sind am schlechtesten und Listen sind näher an der Switch-Anweisung.

Also lautet die Moral der Geschichte: Wenn Sie eine statische, relativ kleine Liste haben, ist die Switch-Anweisung der beste Weg.

29voto

Robert Weber Punkte 299

Das obige Beispiel mit sort kommt der Sache nahe, aber im Falle von Strings verwenden Sie einfach SearchString:

files := []string{"Test.conf", "util.go", "Makefile", "misc.go", "main.go"}
target := "Makefile"
sort.Strings(files)
i := sort.SearchStrings(files, target)
if i < len(files) && files[i] == target {
    fmt.Printf("found \"%s\" at files[%d]\n", files[i], i)
}

https://golang.org/pkg/sort/#SearchStrings

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X