github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/strutil/set.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2019 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package strutil 21 22 // OrderedSet is a set of strings that maintains the order of insertion. 23 // 24 // The order of putting items into the set is retained. Putting items "a", "b" 25 // and then "a", results in order "a", "b". 26 // 27 // External synchronization is required for safe concurrent access. 28 type OrderedSet struct { 29 positionOf map[string]int 30 } 31 32 // Items returns a slice of strings representing insertion order. 33 // 34 // Items is O(N) in the size of the set. 35 func (o *OrderedSet) Items() []string { 36 if len(o.positionOf) == 0 { 37 return nil 38 } 39 items := make([]string, len(o.positionOf)) 40 for item, idx := range o.positionOf { 41 items[idx] = item 42 } 43 return items 44 } 45 46 // Contains returns true if the set contains a given item. 47 // 48 // Contains is O(1) in the size of the set. 49 func (o *OrderedSet) Contains(item string) bool { 50 _, ok := o.positionOf[item] 51 return ok 52 } 53 54 // IndexOf returns the position of an item in the set. 55 func (o *OrderedSet) IndexOf(item string) (idx int, ok bool) { 56 idx, ok = o.positionOf[item] 57 return idx, ok 58 } 59 60 // Put adds an item into the set. 61 // 62 // If the item was not present then it is stored and ordered after all existing 63 // elements. If the item was already present its position is not changed. 64 // 65 // Put is O(1) in the size of the set. 66 func (o *OrderedSet) Put(item string) { 67 if o.positionOf == nil { 68 o.positionOf = make(map[string]int) 69 } 70 71 if _, ok := o.positionOf[item]; ok { 72 return 73 } 74 75 o.positionOf[item] = len(o.positionOf) 76 } 77 78 // Size returns the number of elements in the set. 79 func (o *OrderedSet) Size() int { 80 return len(o.positionOf) 81 }