if statement - make - ¿Go tiene la construcción "if x in" similar a Python?
golang switch example (6)
Sin iterar sobre toda la matriz, ¿cómo puedo verificar si x
en la matriz en Ir?
Como Python: if "x" in array: ...
Acabo de tener una pregunta similar y decidí probar algunas de las sugerencias en este hilo.
He evaluado los mejores y peores escenarios de 3 tipos de búsqueda:
- usando un mapa
- usando una lista
- usando una instrucción de cambio
Aquí está el código de función:
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
}
Los mejores escenarios de casos seleccionan el primer elemento en las listas, en el peor de los casos utilizan valores inexistentes.
aquí están los resultados:
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
El interruptor gana todo el camino, el peor de los casos es mucho más rápido que el mejor. Los mapas son lo peor y la lista está más cerca de cambiar.
Entonces, la moraleja es: si tiene una lista estática y razonablemente pequeña, la instrucción Switch es el camino a seguir.
El ejemplo anterior que utiliza la ordenación está cerca, pero en el caso de cadenas simplemente use 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)
}
Esta es una cita del libro "Programación en Go: Creación de aplicaciones para el siglo XXI":
El uso de una búsqueda lineal simple como esta es la única opción para datos sin clasificar y está bien para segmentos pequeños (hasta cientos de elementos). Pero para cortes más grandes, especialmente si estamos realizando búsquedas repetidamente, la búsqueda lineal es muy ineficiente, ya que en promedio requiere la mitad de los elementos que se comparan cada vez.
Go proporciona un método sort.Search () que usa el algoritmo de búsqueda binario: Esto requiere la comparación de solo elementos log2 (n) (donde n es el número de elementos) cada vez. Para poner esto en perspectiva, una búsqueda lineal de 1000000 elementos requiere 500000 comparaciones en promedio, con el peor de 1000000 comparaciones; una búsqueda binaria necesita como máximo 20 comparaciones, incluso en el peor de los casos.
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)
}
No hay un operador integrado para hacerlo en Go. Necesitas iterar sobre la matriz. Puedes escribir tu propia función para hacerlo, así:
func stringInSlice(a string, list []string) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}
Si desea poder verificar la membresía sin iterar en toda la lista, necesita usar un mapa en lugar de una matriz o segmento, como este:
visitedURL := map[string]bool {
"http://www.google.com": true,
"https://paypal.com": true,
}
if visitedURL[thisSite] {
fmt.Println("Already been here.")
}
Otra opción es usar un mapa como un conjunto. Usas solo las teclas y el valor es algo así como un booleano que siempre es cierto. A continuación, puede comprobar fácilmente si el mapa contiene la clave o no. Esto es útil si necesita el comportamiento de un conjunto, donde si agrega un valor varias veces, solo se incluye una vez en el conjunto.
Aquí hay un ejemplo simple donde agrego números aleatorios como claves a un mapa. Si el mismo número se genera más de una vez, no importa, solo aparecerá en el mapa final una vez. Luego uso un simple if check para ver si una clave está en el mapa o no.
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)
}
}
}
Otra solución si la lista contiene valores estáticos.
Por ejemplo: verificar un valor válido de una lista de valores válidos:
func IsValidCategory(category string) bool {
switch category {
case
"auto",
"news",
"sport",
"music":
return true
}
return false
}