golang why don't we have a set datastructure [closed]
One reason is that it is easy to create a set from map:
s := map[int]bool{5: true, 2: true}
_, ok := s[6] // check for existence
s[8] = true // add element
delete(s, 2) // remove element
Union
s_union := map[int]bool{}
for k, _ := range s1{
s_union[k] = true
}
for k, _ := range s2{
s_union[k] = true
}
Intersection
s_intersection := map[int]bool{}
if len(s1) > len(s2) {
s1, s2 = s2, s1 // better to iterate over a shorter set
}
for k,_ := range s1 {
if s2[k] {
s_intersection[k] = true
}
}
It is not really that hard to implement all other set operations.
Partly, because Go doesn't have generics (so you would need one set-type for every type, or fall back on reflection, which is rather inefficient).
Partly, because if all you need is "add/remove individual elements to a set" and "relatively space-efficient", you can get a fair bit of that simply by using a map[yourtype]bool
(and set the value to true
for any element in the set) or, for more space efficiency, you can use an empty struct as the value and use _, present = the_setoid[key]
to check for presence.
Like Vatine wrote: Since go lacks generics it would have to be part of the language and not the standard library. For that you would then have to pollute the language with keywords set, union, intersection, difference, subset...
The other reason is, that it's not clear at all what the "right" implementation of a set is:
-
There is a functional approach:
func IsInEvenNumbers(n int) bool { if n % 2 == 0 { return true } return false }
This is a set of all even ints. It has a very efficient lookup and union, intersect, difference and subset can easily be done by functional composition.
- Or you do a has-like approach like Dali showed.
A map does not have that problem, since you store something associated with the value.