David K. Bainbridge | 528b318 | 2017-01-23 08:51:59 -0800 | [diff] [blame] | 1 | // Copyright 2013 Canonical Ltd. |
| 2 | // Licensed under the LGPLv3, see LICENCE file for details. |
| 3 | |
| 4 | package set |
| 5 | |
| 6 | import ( |
| 7 | "sort" |
| 8 | ) |
| 9 | |
| 10 | // Strings represents the classic "set" data structure, and contains strings. |
| 11 | type Strings map[string]bool |
| 12 | |
| 13 | // NewStrings creates and initializes a Strings and populates it with |
| 14 | // initial values as specified in the parameters. |
| 15 | func NewStrings(initial ...string) Strings { |
| 16 | result := make(Strings) |
| 17 | for _, value := range initial { |
| 18 | result.Add(value) |
| 19 | } |
| 20 | return result |
| 21 | } |
| 22 | |
| 23 | // Size returns the number of elements in the set. |
| 24 | func (s Strings) Size() int { |
| 25 | return len(s) |
| 26 | } |
| 27 | |
| 28 | // IsEmpty is true for empty or uninitialized sets. |
| 29 | func (s Strings) IsEmpty() bool { |
| 30 | return len(s) == 0 |
| 31 | } |
| 32 | |
| 33 | // Add puts a value into the set. |
| 34 | func (s Strings) Add(value string) { |
| 35 | if s == nil { |
| 36 | panic("uninitalised set") |
| 37 | } |
| 38 | s[value] = true |
| 39 | } |
| 40 | |
| 41 | // Remove takes a value out of the set. If value wasn't in the set to start |
| 42 | // with, this method silently succeeds. |
| 43 | func (s Strings) Remove(value string) { |
| 44 | delete(s, value) |
| 45 | } |
| 46 | |
| 47 | // Contains returns true if the value is in the set, and false otherwise. |
| 48 | func (s Strings) Contains(value string) bool { |
| 49 | _, exists := s[value] |
| 50 | return exists |
| 51 | } |
| 52 | |
| 53 | // Values returns an unordered slice containing all the values in the set. |
| 54 | func (s Strings) Values() []string { |
| 55 | result := make([]string, len(s)) |
| 56 | i := 0 |
| 57 | for key := range s { |
| 58 | result[i] = key |
| 59 | i++ |
| 60 | } |
| 61 | return result |
| 62 | } |
| 63 | |
| 64 | // SortedValues returns an ordered slice containing all the values in the set. |
| 65 | func (s Strings) SortedValues() []string { |
| 66 | values := s.Values() |
| 67 | sort.Strings(values) |
| 68 | return values |
| 69 | } |
| 70 | |
| 71 | // Union returns a new Strings representing a union of the elments in the |
| 72 | // method target and the parameter. |
| 73 | func (s Strings) Union(other Strings) Strings { |
| 74 | result := make(Strings) |
| 75 | // Use the internal map rather than going through the friendlier functions |
| 76 | // to avoid extra allocation of slices. |
| 77 | for value := range s { |
| 78 | result[value] = true |
| 79 | } |
| 80 | for value := range other { |
| 81 | result[value] = true |
| 82 | } |
| 83 | return result |
| 84 | } |
| 85 | |
| 86 | // Intersection returns a new Strings representing a intersection of the elments in the |
| 87 | // method target and the parameter. |
| 88 | func (s Strings) Intersection(other Strings) Strings { |
| 89 | result := make(Strings) |
| 90 | // Use the internal map rather than going through the friendlier functions |
| 91 | // to avoid extra allocation of slices. |
| 92 | for value := range s { |
| 93 | if other.Contains(value) { |
| 94 | result[value] = true |
| 95 | } |
| 96 | } |
| 97 | return result |
| 98 | } |
| 99 | |
| 100 | // Difference returns a new Strings representing all the values in the |
| 101 | // target that are not in the parameter. |
| 102 | func (s Strings) Difference(other Strings) Strings { |
| 103 | result := make(Strings) |
| 104 | // Use the internal map rather than going through the friendlier functions |
| 105 | // to avoid extra allocation of slices. |
| 106 | for value := range s { |
| 107 | if !other.Contains(value) { |
| 108 | result[value] = true |
| 109 | } |
| 110 | } |
| 111 | return result |
| 112 | } |