-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmap.go
More file actions
113 lines (103 loc) · 3.28 KB
/
Copy pathmap.go
File metadata and controls
113 lines (103 loc) · 3.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Package doublemap provides a generic Map[K comparable, V comparable] with operations for getting and setting
// values by key, and the corresponding reverse map operation of getting and setting keys by values. The Map is
// not thread-safe.
//
// Quickstart:
//
// package main
//
// import (
// "fmt"
//
// "github.com/rasteric/doublemap"
// )
//
// func main() {
// m := doublemap.New[string, int]()
// m.Set("first", 1)
// m.Set("second", 2)
// m.Set("third", 3)
// v, _ := m.Get("first")
// fmt.Println(v)
// k, _ := m.ByValue(3)
// fmt.Println(k)
// }
package doublemap
// A Map stores keys and values in a way that makes reverse mapping from values to keys efficient at the
// cost of additional memory and storage complexity. You should only use this map if your values are unique
// - otherwise the value-related lookup functions make no sense and Remove might have unexpected results!
type Map[K comparable,V comparable] struct {
kv map[K]V
vk map[V]K
}
// New creates a new double map.
func New[K, V comparable]() *Map[K, V] {
return &Map[K, V]{ kv: make(map[K]V), vk: make(map[V]K) }
}
// Get returns the value for the given key and true, the null value of the value type and false if no value
// was stored for this key.
func (m *Map[K, V]) Get(key K) (V, bool) {
value, ok := m.kv[key]
return value, ok
}
// Set sets a value for the given key.
func (m *Map[K, V]) Set(key K, value V) {
m.kv[key] = value
m.vk[value] = key
}
// Remove removes the key and value mapping based on the given key. True is returned if the mapping was removed,
// false is returned when there was no mapping for the key in the first place.
func (m *Map[K, V]) Remove(key K) bool {
value, ok := m.Get(key)
if ok {
delete(m.kv, key)
delete(m.vk, value)
return true
}
return false
}
// ByValue returns the key for a given value and true, the key type's null value and false if no key was
// stored for this value.
func (m *Map[K, V]) ByValue(value V) (K, bool) {
key, ok := m.vk[value]
return key, ok
}
// RemoveByValue removes a given key-value mapping by the given value. True is returned if the mapping has been
// removed, false is returned if there was no such value in the double map in the first place.
func (m Map[K, V]) RemoveByValue(value V) bool {
key, ok := m.ByValue(value)
if ok {
delete(m.kv, key)
delete(m.vk, value)
return true
}
return false
}
// Copy creates a copy of the key-value mapping. This operation is fairly slow but faster than using Get and Set
// manually. The copy is not deep, i.e., any key and values are just copied using ordinary assignment.
func (m *Map[K, V]) Copy() *Map[K, V] {
m2 := Map[K, V]{}
for k, v := range m.kv {
m2.kv[k] = v
m2.vk[v] = k
}
return &m2
}
// Walk traverses key-value pairs in the map and provides them to the given function in unspecified order
// until the function returns false.
func (m *Map[K, V]) Walk(fn func (key K, value V) bool) {
for k, v := range m.kv {
if !fn(k, v) {
break
}
}
}
// Clear clears the map, removing all key-valie pairs in it.
func (m *Map[K, V]) Clear() {
for k := range m.kv { // better than one loop since this is optimized by compiler
delete(m.kv, k)
}
for k:= range m.vk {
delete(m.vk, k)
}
}