2
votes

I want to create an array that contains unique strings. How can I do that?

var paths = make([]string, 0)

func main() {
    // Members are added dynamically
    paths = append(paths, "aaa")
    paths = append(paths, "bbb")
    paths = append(paths, "bbb")
    paths = append(paths, "ccc")

    // convert ["aaa", "bbb", "bbb", "ccc"] -> ["aaa", "bbb", "ccc"] 
    // or can I use some class that disallow the same string automaticaly?
}
1

1 Answers

12
votes

If you want a collection of unique elements, that is the Set data type. Go does not have a set data type, but you can use a map[string]bool to act as a set.

For a "nice" set, use a map with bool value type (with true values) and exploit the zero value. For a set with the smallest memory footprint, use a map with struct{} value type as values of struct{} type occupy no memory; and use the comma-ok idiom to tell if a value is in the set / map.

Here's how the "nice" version of set looks like. Instead of a slice add your elements to a map[string]bool as the key with a true as the value:

m := make(map[string]bool)

m["aaa"] = true
m["bbb"] = true
m["bbb"] = true
m["ccc"] = true

To check if an element is already in the collection (map), you can simply use an index expression:

exists := m["somevalue"]

This exploits the zero value, that is if the map does not yet contain an element, the zero value of the value type is returned which is false in case of bool type, properly indicating that the element is not in the collection.

Elements in a map have no fixed order. If you need to keep the order (e.g. insertion order), then use a slice (to remember the order) and a map (to tell if an element to be added is new). This is easiest with a helper add() function:

var m = make(map[string]bool)
var a = []string{}

func main() {
    add("aaa")
    add("bbb")
    add("bbb")
    add("ccc")
}

func add(s string) {
    if m[s] {
        return // Already in the map
    }
    a = append(a, s)
    m[s] = true
}