web-dev-qa-db-fra.com

Go a-t-il une construction "if x in" similaire à Python?

Sans itérant sur tout le tableau, comment puis-je vérifier si x dans un tableau utilisant Go? La langue a-t-elle une construction?

Comme Python: if "x" in array: ...

239
user1529891

Il n'y a pas d'opérateur intégré pour le faire dans Go. Vous devez parcourir le tableau. Vous pouvez écrire votre propre fonction pour le faire, comme ceci:

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

Si vous voulez pouvoir vérifier l'appartenance sans parcourir la liste en entier, vous devez utiliser une carte au lieu d'un tableau ou d'une tranche, comme ceci:

visitedURL := map[string]bool {
    "http://www.google.com": true,
    "https://Paypal.com": true,
}
if visitedURL[thisSite] {
    fmt.Println("Already been here.")
}
291
andybalholm

Une autre solution si la liste contient des valeurs statiques.

exemple: rechercher une valeur valide dans une liste de valeurs valides:

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

Voici une citation du livre "Programmation in Go: créer des applications pour le 21e siècle":

Utiliser une recherche linéaire simple comme celle-ci est la seule option pour les données non triées et convient pour de petites tranches (jusqu'à des centaines d'éléments). Mais pour les grandes tranches, en particulier si nous effectuons des recherches de manière répétée, la recherche linéaire est très inefficace et nécessite en moyenne la moitié des éléments à comparer à chaque fois.

Go fournit une méthode sort.Search () qui utilise l'algorithme de recherche binaire: Cette méthode nécessite la comparaison d'éléments log2 (n) seulement (où n est le nombre d'éléments) à chaque fois. Pour mettre cela en perspective, une recherche linéaire de 1 000 éléments nécessite 500 000 comparaisons en moyenne, avec le pire cas de 1 000 comparaisons; une recherche binaire nécessite au maximum 20 comparaisons, même dans le pire des cas.

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

47
AlexTT

L'exemple ci-dessus utilisant la méthode de tri est fermé, mais dans le cas de chaînes, utilisez simplement 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

22
Robert Weber

Juste une question similaire et a décidé d'essayer certaines des suggestions dans ce fil.

J'ai comparé les meilleurs et les pires scénarios de 3 types de recherche:

  • en utilisant une carte
  • en utilisant une liste
  • en utilisant une instruction switch

voici le code de fonction:

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
}

dans le meilleur des cas, les scénarios choisissent le premier élément de la liste, dans le pire des cas, une valeur non existante.

voici les résultats:

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

Switch gagne tout le chemin, le pire des cas est infiniment plus rapide que le meilleur des cas. Les cartes sont les pires et la liste est plus proche du changement.

Donc, la morale est la suivante: si vous avez une liste statique, raisonnablement petite, l’instruction Switch est la solution.

17
Igor

Une autre option consiste à utiliser une carte comme un ensemble. Vous n'utilisez que les clés et la valeur devient un booléen toujours vrai. Ensuite, vous pouvez facilement vérifier si la carte contient la clé ou non. Ceci est utile si vous avez besoin du comportement d'un ensemble, où si vous ajoutez une valeur plusieurs fois, ce n'est qu'une fois dans l'ensemble.

Voici un exemple simple où j'ajoute des nombres aléatoires comme clés à une carte. Si le même nombre est généré plus d'une fois, peu importe, il n'apparaîtra qu'une seule fois dans la carte finale. Ensuite, j’utilise un simple if pour vérifier si une clé est sur la carte ou non.

package main

import (
    "fmt"
    "math/Rand"
)

func main() {
    var MAX int = 10

    m := make(map[int]bool)

    for i := 0; i <= MAX; i++ {
        m[Rand.Intn(MAX)] = true
    }

    for i := 0; i <= MAX; i++ {
        if _, ok := m[i]; ok {
            fmt.Printf("%v is in map\n", i)
        } else {
            fmt.Printf("%v is not in map\n", i)
        }
    }
}

ici c'est sur le terrain de je

7
nobled