I really like google golang but could some one explain what the rationale is for the implementors having left out a basic data structure such as sets from the standard library?
4
One potential reason for this omission is that it’s really easy to model sets with a map.
To be honest I think it’s a bit of an oversight too, however looking at Perl, the story’s exactly the same. In Perl you get lists and hashtables, in Go you get arrays, slices, and maps. In Perl you’d generally use a hashtable for any and all problems relating to a set, the same is applicable to Go.
Example
to imitate a set ints in Go, we define a map:
set := make(map[int]bool)
To add something is as easy as:
i := valueToAdd()
set[i] = true
Deleting something is just
delete(set, i)
And the potential awkwardness of this construct is easily abstracted away:
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
}
And delete and get can be defined similarly, I have the complete implementation here . The major disatvantage here is the fact that go doesn’t have generics. However it is possible to do this with interface{}
in which case you’d have cast the results of get.
10
I think this has to do with golang
focus on simplicity. set
s become really useful with difference
, intersection
, union
, issubset
, and so on.. methods. Perhaps golang
team felt that it is too much for one data structure. But otherwise a “dumb set” that only has add
, contains
and remove
can be easily replicated with map
as explained by @jozefg.
1
The previous answer works ONLY IF the key are a built-in type. To complement the previous answer, here is a way to implement a set whose elements are user-defined types:
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))}
}
3