2012-05-07 14 views

Respuesta

130

Mostafa ya ha señalado que dicho método es trivial de escribir, y mkb le dio una pista para usar la búsqueda binaria del paquete de clasificación. Pero si vas a hacer muchos de estos controles, también podrías considerar usar un mapa.

Es trivial comprobar si existe una clave de mapa específica utilizando la expresión value, ok := yourmap[key]. Como no está interesado en el valor, también puede crear un map[string]struct{} por ejemplo. Usar un struct{} vacío aquí tiene la ventaja de que no requiere espacio adicional y el tipo de mapa interno de Go está optimizado para ese tipo de valores. Por lo tanto, map[string] struct{} es una opción popular para los sets en el mundo Go.

+1

+1 para explicar bien la solución del mapa. – Mostafa

+0

no estoy 100% seguro de cómo funciona todo esto, (esta es prácticamente mi primera oportunidad en GO) pero parece ser lo que estoy buscando. ¡Gracias! – vosmith

+9

También tenga en cuenta que debe escribir 'struct {} {}' para obtener el valor de la estructura vacía para que pueda pasarla a su mapa cuando desee agregar un elemento. Pruébelo y si tiene algún problema, no dude en preguntar. También puede usar la solución de Mostafa si es más fácil de comprender (a menos que tenga grandes cantidades de datos). – tux21b

80

No, tal método no existe, pero es trivial para escribir:

func contains(s []int, e int) bool { 
    for _, a := range s { 
     if a == e { 
      return true 
     } 
    } 
    return false 
} 

Se puede utilizar un mapa si es que las operaciones de búsqueda es una parte importante de su código, pero los mapas de haber costado demasiado.

+87

En realidad no es trivial, porque usted tiene que escribir una para cada tipo que se utiliza, y porque no hay sobrecarga, hay que nombrar a cada función de manera diferente, como en C. append() puede funcionar genéricamente porque tiene soporte de tiempo de ejecución especial. Un contenido genérico sería útil por la misma razón, pero realmente la solución genérica es solo soporte de genéricos en el lenguaje. – Eloff

+10

@Eloff 'interfaz {}' –

+1

@Alex Lockwood ¿funcionará realmente con las interfaces? –

6

En lugar de utilizar un slice, map puede ser una solución mejor.

ejemplo sencillo:

package main 

import "fmt" 


func contains(slice []string, item string) bool { 
    set := make(map[string]struct{}, len(slice)) 
    for _, s := range slice { 
     set[s] = struct{}{} 
    } 

    _, ok := set[item] 
    return ok 
} 

func main() { 

    s := []string{"a", "b"} 
    s1 := "a" 
    fmt.Println(contains(s, s1)) 

} 

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

+13

En su forma actual, este código no ofrece ningún beneficio, ya que no tiene sentido construir un mapa a partir de una porción si solo va a utilizarlo una vez. - Para ser útil, este código debería proporcionar una función 'sliceToMap' que hace toda la preparación. Después de eso, consultar el mapa es trivial y eficiente. –

+0

Gracias por el código de muestra. – xpt

2

Puede utilizar el reflejan paquete para iterar sobre una interfaz cuyo tipo concreto es una rebanada:

func HasElem(s interface{}, elem interface{}) bool { 
    arrV := reflect.ValueOf(s) 

    if arrV.Kind() == reflect.Slice { 
     for i := 0; i < arrV.Len(); i++ { 

      // XXX - panics if slice element points to an unexported struct field 
      // see https://golang.org/pkg/reflect/#Value.Interface 
      if arrV.Index(i).Interface() == elem { 
       return true 
      } 
     } 
    } 

    return false 
} 

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

2

No estoy seguro de que los genéricos sean necesarios aquí, solo necesita un contrato para su comportamiento deseado. Hacer lo siguiente no es más de lo que tendrías que hacer en otros idiomas si quisieras que quisieras que tus propios objetos se comportaran en colecciones, anulando Equals() y GetHashCode() por ejemplo.

type Identifiable interface{ 
    GetIdentity() string 
} 

func IsIdentical(this Identifiable, that Identifiable) bool{ 
    return (&this == &that) || (this.GetIdentity() == that.GetIdentity()) 
} 

func contains(s []Identifiable, e Identifiable) bool { 
    for _, a := range s { 
     if IsIdentical(a,e) { 
      return true 
     } 
    } 
    return false 
} 
Cuestiones relacionadas