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?
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?
Réponses:
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.
map[int]bool
on peut utiliser à la map[int]struct{}
place. Je préfère le dernier.
map[int]struct{}
.. Le struct{}
prend 0 octet.
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é").
Je pense que cela a à voir avec l' golang
accent mis sur la simplicité. set
s deviennent vraiment utiles avec difference
, intersection
, union
, issubset
et 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
, contains
et remove
peut être facilement répliqué avec map
comme expliqué par @jozefg.
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))}
}
type mySet map[IntPoint]bool
fonctionne 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 Equals
méthode devrait être juste p1 == p2
.
Contains
prend 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 map
fournie par le type. Des solutions encore plus rapides prenant en compte le comportement du cache, etc. existent également.