Définit la structure de données dans Golang

70

J'aime beaucoup google golang, mais est-ce que quelqu'un pourrait expliquer la raison pour laquelle les développeurs ont laissé de côté une structure de données de base telle que des ensembles de la bibliothèque standard?

Cobie
la source
8
La langue s'appelle réellement Go, not golang
jozefg
92
Mais "Golang" est plus consultable
Matt
18
Beaucoup plus consultable. Googling "go set" renvoie des images d'une planche de bois avec des pièces noires et blanches.
Doug Richardson

Réponses:

69

Une des raisons possibles de cette omission est qu’il est très facile de modéliser des ensembles avec une carte.

Pour être honnête, je pense que c'est un peu un oubli aussi, mais en regardant Perl, l'histoire est exactement la même. En Perl, vous obtenez des listes et des tables de hachage. En Go, vous obtenez des tableaux, des tranches et des cartes. En Perl, vous utiliseriez généralement une table de hachage pour tous les problèmes liés à un ensemble, il en va de même pour Go.

Exemple

pour imiter un ensemble dans Go, nous définissons une carte:

set := make(map[int]bool)

Ajouter quelque chose est aussi simple que:

i := valueToAdd()
set[i] = true

Supprimer quelque chose, c'est juste

delete(set, i)

Et la gêne potentielle de cette construction est facilement résumée:

type IntSet struct {
    set map[int]bool
}

func (set *IntSet) Add(i int) bool {
    _, found := set.set[i]
    set.set[i] = true
    return !found   //False if it existed already
}

Et supprimer et obtenir peuvent être définis de la même façon, j'ai l'implémentation complète ici . Le désavantage majeur ici est le fait que go n’a pas de génériques. Cependant, il est possible de faire cela avec les interface{}cas où vous auriez jeté les résultats de get.

Jozefg
la source
3
Voici ma version légèrement révisée avec les méthodes Contains et Size: play.golang.org/p/tDdutH672-
Rick-777
19
Au lieu de map[int]boolon peut utiliser à la map[int]struct{}place. Je préfère le dernier.
pepper_chico
20
map[int]struct{}.. Le struct{}prend 0 octet.
Boopathi Rajaa
2
github.com/fatih/set est une implémentation de mon basé sur des cartes et des structures vides. C'est thread-safe et a une simple api.
Fatih Arslan
6
Avec map[int]struct{}vous, vous ne pouvez pas if mymap["key"] {vérifier votre adhésion. Google recommande d'utiliserbool (recherchez "Un ensemble peut être implémenté").
Timmmm
3

Je pense que cela a à voir avec l' golangaccent mis sur la simplicité. sets deviennent vraiment utiles avec difference, intersection, union, issubsetet ainsi de suite .. méthodes. L’ golangéquipe a peut - être estimé que c’était trop pour une seule structure de données. Mais sinon, un "jeu stupide" qui a seulement add, containset removepeut être facilement répliqué avec mapcomme expliqué par @jozefg.

Akavall
la source
je ne suis pas d'accord. un ensemble est principalement utilisé pour les vérifications d'adhésion et la sémantique d'uniqeness. une mise en œuvre définie serait parfaitement utilisable sans ces méthodes. Cela étant dit, ils sont également triviaux à mettre en œuvre.
Sedat Kapanoglu
2

La réponse précédente ne fonctionne que si les clés sont un type intégré. Pour compléter la réponse précédente, voici un moyen d'implémenter un ensemble dont les éléments sont des types définis par l'utilisateur:

package math

// types

type IntPoint struct {
    X, Y int
}

// set implementation for small number of items
type IntPointSet struct {
    slice []IntPoint 
}

// functions

func (p1 IntPoint) Equals(p2 IntPoint) bool {
    return (p1.X == p2.X) && (p1.Y == p2.Y)
}

func (set *IntPointSet) Add(p IntPoint) {
    if ! set.Contains(p) {
        set.slice = append(set.slice, p)
    }
}

func (set IntPointSet) Contains(p IntPoint) bool {
  for _, v := range set.slice {
    if v.Equals(p) {
      return true
    }
  }
  return false
}

func (set IntPointSet) NumElements() int {
    return len(set.slice)
}

func NewIntPointSet() IntPointSet {
  return IntPointSet{(make([]IntPoint, 0, 10))}
}
Amahfouz
la source
8
"Fonctionne UNIQUEMENT SI les clés sont de type intégré" est incorrect . type mySet map[IntPoint]boolfonctionne parfaitement bien. Tout ce qui est requis du type de clé utilisé dans une carte est qu'il possède ==et!= . L'égalité des types de structure est bien définie, votre Equalsméthode devrait être juste p1 == p2.
Dave C
1
Il est vrai que l’égalité des structures est bien définie, mais si la structure contient des mappes ou des tranches sous forme de champs, elles seront comparées par référence plutôt que par valeur. Cela peut ne pas être ce que vous voulez.
Chaim-Leib Halbert
1
Je prends un peu de problème avec cette solution, car Containsprend du temps linéaire, alors que aMap[]prend du temps constant, quel que soit le nombre de membres. Une meilleure solution créerait en interne une clé unique basée sur le contenu de chaque membre et exploiterait l'interrogation à temps constant mapfournie par le type. Des solutions encore plus rapides prenant en compte le comportement du cache, etc. existent également.
Chaim-Leib Halbert