-
Notifications
You must be signed in to change notification settings - Fork 1
/
orderedmap.go
219 lines (186 loc) · 4.95 KB
/
orderedmap.go
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
// Package orderedmap is a Go implementation of Python's OrderedDict class, a map
// that preserves the order of insertion, so key:value pairs can be iterated in
// the order they where added.
// It can also be used as a stack (LIFO) or queue (FIFO).
package orderedmap
import "fmt"
// OrderedMap class
type OrderedMap struct {
table map[interface{}]*node
root *node
}
// NewOrderedMap creates an empty OrderedMap
func NewOrderedMap() *OrderedMap {
root := newNode(nil, nil, nil, nil) // sentinel Node
root.Next, root.Prev = root, root
om := &OrderedMap{
table: make(map[interface{}]*node),
root: root,
}
return om
}
// Len returns the number of elements in the Map
func (om *OrderedMap) Len() int {
return len(om.table)
}
// Set the key value, if the key overwrites an existing entry, the original
// insertion position is left unchanged, otherwise the key is inserted at the end.
func (om *OrderedMap) Set(key interface{}, value interface{}) {
if node, ok := om.table[key]; !ok {
// New Node
root := om.root
node := newNode(key, value, root, root.Prev)
root.Prev.Next = node
root.Prev = node
om.table[key] = node
} else {
// Update existing node value
node.Value = value
}
}
// Get the value of an existing key, leaving the map unchanged
func (om *OrderedMap) Get(key interface{}) (value interface{}, ok bool) {
if node, isOk := om.table[key]; !isOk {
value, ok = nil, false
} else {
value, ok = node.Value, true
}
return
}
// GetLast return the key and value for the last element added, leaving
// the map unchanged
func (om *OrderedMap) GetLast() (key interface{}, value interface{}, ok bool) {
if len(om.table) == 0 {
key, value, ok = nil, nil, false
} else {
node := om.root.Prev
key, value, ok = node.Key, node.Value, true
}
return
}
// GetFirst returns the key and value for the first element, leaving the map unchanged
func (om *OrderedMap) GetFirst() (key interface{}, value interface{}, ok bool) {
if len(om.table) == 0 {
key, value, ok = nil, nil, false
} else {
node := om.root.Next
key, value, ok = node.Key, node.Value, true
}
return
}
// Delete a key:value pair from the map.
func (om *OrderedMap) Delete(key interface{}) {
if node, ok := om.table[key]; ok {
node.Next.Prev = node.Prev
node.Prev.Next = node.Next
delete(om.table, key)
}
}
// Pop and return key:value for the newest or oldest element on the OrderedMap
func (om *OrderedMap) Pop(last bool) (key interface{}, value interface{}, ok bool) {
if last {
key, value, ok = om.GetLast()
} else {
key, value, ok = om.GetFirst()
}
if ok {
om.Delete(key)
}
return
}
// PopLast is a shortcut to Pop the last element
func (om *OrderedMap) PopLast() (key interface{}, value interface{}, ok bool) {
return om.Pop(true)
}
// PopFirst is a shortcut to Pop the first element
func (om *OrderedMap) PopFirst() (key interface{}, value interface{}, ok bool) {
return om.Pop(false)
}
// Move an existing key to either the end of the OrderedMap
func (om *OrderedMap) Move(key interface{}, last bool) (ok bool) {
var moved *node
// Remove from current position
anode, ok := om.table[key]
if !ok {
return false
}
anode.Next.Prev = anode.Prev
anode.Prev.Next = anode.Next
moved = anode
// Insert at the start or end
root := om.root
if last {
moved.Next = root
moved.Prev = root.Prev
root.Prev.Next = moved
root.Prev = moved
} else {
moved.Prev = root
moved.Next = root.Next
root.Next.Prev = moved
root.Next = moved
}
return true
}
// MoveLast is a shortcut to Move a key to the end o the map
func (om *OrderedMap) MoveLast(key interface{}) (ok bool) {
return om.Move(key, true)
}
// MoveFirst is a shortcut to Move a key to the beginning of the map
func (om *OrderedMap) MoveFirst(key interface{}) (ok bool) {
return om.Move(key, false)
}
// MapIterator is a iterator over an OrderedMap
type MapIterator struct {
curr *node
root *node
reverse bool
}
// Iter creates a map iterator
func (om *OrderedMap) Iter() *MapIterator {
return &MapIterator{
curr: om.root,
root: om.root,
reverse: false,
}
}
// IterReverse creates a reverse order map iterator
func (om *OrderedMap) IterReverse() *MapIterator {
return &MapIterator{
curr: om.root,
root: om.root,
reverse: true,
}
}
// Next key:value pair
func (mi *MapIterator) Next() (key interface{}, value interface{}, ok bool) {
// Already finished
if mi.curr == nil {
return nil, nil, false
}
// Advance pointer
if mi.reverse {
mi.curr = mi.curr.Prev
} else {
mi.curr = mi.curr.Next
}
// This is the last iteration
if mi.curr == mi.root {
mi.curr = nil
key, value, ok = nil, nil, false
} else {
key, value, ok = mi.curr.Key, mi.curr.Value, true
}
return
}
// String interface
func (om *OrderedMap) String() string {
buffer := make([]string, om.Len())
iter := om.Iter()
index := 0
for key, value, ok := iter.Next(); ok; key, value, ok = iter.Next() {
buffer[index] = fmt.Sprintf("%v:%v, ", key, value)
index++
}
return fmt.Sprintf("OrderedMap%v", buffer)
}