Golang, ¿por qué no tenemos una estructura de datos establecida [cerrada]

129

Estoy tratando de resolver el ejercicio "1.4", que requiere que tenga un conjunto. Puedo crear un tipo de conjunto, pero ¿por qué el idioma no viene con uno? vaya, habiendo venido de google, donde también se originó la guayaba, ¿por qué los diseñadores de idiomas no optaron por agregar soporte para estructuras de datos fundamentales? ¿Por qué obligar a sus usuarios a crear sus propias implementaciones para algo tan básico como un conjunto?

anjanb
fuente
11
hmmm preguntándose por qué los votos negativos? Vengo del mundo de Java, donde teníamos un set casi desde el principio, incluso sin genéricos. Por lo tanto, este comportamiento me parece un poco extraño
anjanb

Respuestas:

83

En parte, porque Go no tiene genéricos (por lo que necesitaría un tipo de conjunto para cada tipo, o recurrir a la reflexión, que es bastante ineficiente).

En parte, porque si todo lo que necesita es "agregar / eliminar elementos individuales a un conjunto" y "relativamente eficiente en espacio", puede obtener un poco de eso simplemente usando un map[yourtype]bool(y establezca el valor truepara cualquier elemento en el conjunto ) o, para una mayor eficiencia en el espacio, puede usar una estructura vacía como valor y usar _, present = the_setoid[key]para verificar la presencia.

Vatine
fuente
1
Además, parece estar en el espíritu de Go escribirlo en su propio código, ya sea "integrando" el conjunto en otro código, o definir su propio tipo de conjunto cuando sea necesario. De todos modos, usar por ejemplo un std :: set <T> en C ++ siempre ocurre como parte de una implementación de función o implementando alguna otra estructura de datos. Por lo tanto, simplemente implemente esa otra estructura de datos directamente usando mapas y sectores y cualquier otro bloque de construcción que necesite, pero sin ningún conjunto integrado. De todos modos, cada uso de un conjunto lo usará de manera ligeramente diferente :)
Bjarke Ebert
1
Pero, por lo general, no necesita un conjunto <Foo> por sí mismo, utiliza un conjunto <Foo> como parte de la implementación de algo más grande. He visto toneladas de código donde las cosas que debe hacer para incluir un componente "reutilizable" es mucho peor que simplemente evitar la necesidad. Entonces, aquí tenemos un conjunto <Foo>, esa función allí necesita un conjunto <Bar>, oops, ¿tenemos covarianza todavía o qué tal hacer una WrapperFactory para hacer que esta cosa se vea así, etc. Tal vez esa otra función realmente solo necesita una interfaz que pueda verificar la membresía, así que no le envíe un conjunto <Foo>.
Bjarke Ebert
42
Entonces, si no tiene genéricos, ¿cómo se implementa el mapa 'genérico'?
Fermín Silva
26
Tenga en cuenta que si desea guardar bytes, puede usar en map[T]struct{}lugar de map[T]bool.
Emersión
44
Echar un vistazo a emersion.fr/blog/2017/sets-in-go
emersión
69

Una razón es que es fácil crear un conjunto de mapas:

s := map[int]bool{5: true, 2: true}
_, ok := s[6] // check for existence
s[8] = true // add element 
delete(s, 2) // remove element

Unión

s_union := map[int]bool{}
for k, _ := range s1{
    s_union[k] = true
}
for k, _ := range s2{
    s_union[k] = true
}

Intersección

s_intersection := map[int]bool{}
for k,_ := range s1 { 
  if s2[k] {
    s_intersection[k] = true
  }
}

Realmente no es tan difícil implementar todas las demás operaciones de conjuntos.

Salvador Dalí
fuente
10
Verificar la existencia es simplemente indexar el mapa. Dado que si no está en él, el valor cero (que es false) lo dirá correctamente. No es necesario el idioma de coma-ok para probar.
icza
2
La implementación para la intersección se ve así por diferencia.
musiphil
1
@ Kittsil gracias. Actualizado.
Salvador Dali
34
Es más óptimo usarlo en map[int]struct{}lugar de hacerlo bool, porque una estructura vacía ocupa 0 bytes en la memoria. Recientemente he escrito un resumen de
BG Adrian
13
Eso no es tan fácil. Solo tener que escribir ese código en todas partes donde necesites usar un Set me parece ridículo en estos días. El soporte de colecciones debe ser proporcionado por cualquier idioma. Piensa que una mejor respuesta es que Go aún no es tan maduro. Estoy seguro de que habrá bibliotecas para cubrir eso pronto.
Stef
5

Como Vatine escribió: Dado que go carece de genéricos, debería ser parte del lenguaje y no de la biblioteca estándar. Para eso, tendría que contaminar el idioma con palabras clave set, union, intersection, difference, subset ...

La otra razón es que no está claro en absoluto cuál es la implementación "correcta" de un conjunto:

  1. Hay un enfoque funcional:

    func IsInEvenNumbers(n int) bool {
        if n % 2 == 0 {
            return true
        }
       return false
    }

Este es un conjunto de todas las entradas pares. Tiene una búsqueda muy eficiente y la unión, la intersección, la diferencia y el subconjunto se pueden hacer fácilmente por composición funcional.

  1. O haces un enfoque similar al que mostró Dali.

Un mapa no tiene ese problema, ya que almacena algo asociado con el valor.

0x434D53
fuente
2
Para manejar conjuntos incorporados, Pascal sobrecarga un grupo de operadores binarios (dos argumentos): +para unión, -para diferencia, *para intersección, <=para subconjunto, >=para superconjunto, =para igualdad, <>para desigualdad y inpara membresía. Entonces, en Go, sería solo una nueva palabra clave - in. Por otro lado, los conjuntos integrados de Pascal solo funcionan en "ordinales", es decir, cualquier tipo que tenga una representación subyacente de un valor entero de algún tamaño.
kostix
9
El hecho de que haya múltiples formas de implementar un conjunto no ha impedido que muchos otros idiomas los proporcionen.
augurar el
@kostix: Go incluso podría usar la sintaxis s[key](como si sfuera a map[T]bool) en lugar de key in s.
musiphil
2
¿Alguna razón para no simplemente regresar n % 2 == 0?
João Andrade
4

Otra posibilidad es usar conjuntos de bits, para los cuales hay al menos un paquete o puede usar el paquete grande incorporado . En este caso, básicamente necesita definir una forma de convertir su objeto en un índice.

Will Fitzgerald
fuente
1
Debo señalar que escribí la versión original del paquete de bitset mencionado anteriormente.
Will Fitzgerald el