web-dev-qa-db-fra.com

Définit la structure des données à Golang

J'aime vraiment google golang, mais quelqu'un pourrait-il expliquer pourquoi les implémenteurs ont omis une structure de données de base comme les ensembles de la bibliothèque standard?

69
cobie

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 aussi un peu un oubli, mais en regardant Perl, l'histoire est exactement la même. En Perl, vous obtenez des listes et des tables de hachage, dans 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, la même chose s'applique à Go.

Exemple

pour imiter un set ints 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 est juste

delete(set, i)

Et la maladresse 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 manière similaire, 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 le faire avec interface{} auquel cas vous auriez jeté les résultats de get.

70
Daniel Gratzer

Je pense que cela a à voir avec golang se concentrer sur la simplicité. sets deviennent vraiment utiles avec les méthodes difference, intersection, union, issubset, etc. Peut-être que l'équipe de golang a estimé que c'était trop pour une seule structure de données. Mais sinon, un "ensemble stupide" qui n'a que add, contains et remove peut être facilement répliqué avec map comme expliqué par @jozefg.

3
Akavall

La réponse précédente fonctionne UNIQUEMENT SI la clé est de 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))}
}
2
amahfouz