@@ -3,44 +3,65 @@ package orderedmap
3
3
import (
4
4
"bytes"
5
5
"encoding/json"
6
- "reflect"
7
6
"slices"
8
7
)
9
8
10
- // Map is a container of properties
11
- type Map [K comparable , V any ] struct {
12
- kv map [K ]V
13
- o []K
9
+ // Map is a map that keeps ordering insertion.
10
+ type Map [K any , V any ] interface {
11
+ Get (K ) V
12
+ Set (K , V )
13
+ Keys () []K
14
+ Merge (... Map [K , V ]) Map [K , V ]
15
+ SortKeys (f func (x , y K ) int )
16
+ SortStableKeys (f func (x , y K ) int )
17
+ }
18
+
19
+ // NewWithConversionFunc creates a map using the given conversion function
20
+ // to convert non-comparable key type to comparable items.
21
+ // The conversion function must be bijective.
22
+ func NewWithConversionFunc [K any , V any , C comparable ](conv func (K ) C ) Map [K , V ] {
23
+ return & mapImpl [K , V , C ]{
24
+ conv : conv ,
25
+ kv : map [C ]V {},
26
+ o : []K {},
27
+ }
14
28
}
15
29
16
- // New returns a new Map
17
- func New [K comparable , V any ]() * Map [K , V ] {
18
- return & Map [K , V ]{
19
- kv : map [K ]V {},
20
- o : []K {},
30
+ // New creates a map
31
+ func New [K comparable , V any ]() * mapImpl [K , V , K ] {
32
+ return & mapImpl [K , V , K ]{
33
+ conv : func (in K ) K { return in }, // identity
34
+ kv : map [K ]V {},
35
+ o : []K {},
21
36
}
22
37
}
23
38
39
+ type mapImpl [K any , V any , C comparable ] struct {
40
+ conv func (K ) C
41
+ kv map [C ]V
42
+ o []K
43
+ }
44
+
24
45
// Get retrieves the value corresponding to key
25
- func (m * Map [K , V ]) Get (key K ) V {
26
- return m .kv [key ]
46
+ func (m * mapImpl [K , V , C ]) Get (key K ) V {
47
+ return m .kv [m . conv ( key ) ]
27
48
}
28
49
29
50
// GetOk retrieves the value corresponding to key and returns a true/false indicator
30
51
// to check if the key is present in the map (true if the key is present)
31
- func (m * Map [K , V ]) GetOk (key K ) (V , bool ) {
32
- v , ok := m .kv [key ]
52
+ func (m * mapImpl [K , V , C ]) GetOk (key K ) (V , bool ) {
53
+ v , ok := m .kv [m . conv ( key ) ]
33
54
return v , ok
34
55
}
35
56
36
57
// ContainsKey returns true if the map contains the specified key
37
- func (m * Map [K , V ]) ContainsKey (key K ) bool {
38
- _ , has := m .kv [key ]
58
+ func (m * mapImpl [K , V , C ]) ContainsKey (key K ) bool {
59
+ _ , has := m .kv [m . conv ( key ) ]
39
60
return has
40
61
}
41
62
42
63
// MarshalJSON marshal the map into json mantaining the order of the key
43
- func (m * Map [K , V ]) MarshalJSON () ([]byte , error ) {
64
+ func (m * mapImpl [K , V , C ]) MarshalJSON () ([]byte , error ) {
44
65
if m .Size () == 0 {
45
66
return []byte ("{}" ), nil
46
67
}
@@ -52,7 +73,7 @@ func (m *Map[K, V]) MarshalJSON() ([]byte, error) {
52
73
return nil , err
53
74
}
54
75
buf .WriteByte (':' )
55
- if err := encoder .Encode (m .kv [k ]); err != nil {
76
+ if err := encoder .Encode (m .kv [m . conv ( k ) ]); err != nil {
56
77
return nil , err
57
78
}
58
79
buf .WriteByte (',' )
@@ -63,24 +84,26 @@ func (m *Map[K, V]) MarshalJSON() ([]byte, error) {
63
84
}
64
85
65
86
// Set inserts or replaces an existing key-value pair in the map
66
- func (m * Map [K , V ]) Set (key K , value V ) {
67
- if _ , has := m .kv [key ]; has {
87
+ func (m * mapImpl [K , V , C ]) Set (key K , value V ) {
88
+ compKey := m .conv (key )
89
+ if _ , has := m .kv [compKey ]; has {
68
90
m .Remove (key )
69
91
}
70
- m .kv [key ] = value
92
+ m .kv [compKey ] = value
71
93
m .o = append (m .o , key )
72
94
}
73
95
74
96
// Size returns the number of elements in the map
75
- func (m * Map [K , V ]) Size () int {
97
+ func (m * mapImpl [K , V , C ]) Size () int {
76
98
return len (m .kv )
77
99
}
78
100
79
101
// Remove removes the key from the map
80
- func (m * Map [K , V ]) Remove (key K ) {
81
- delete (m .kv , key )
102
+ func (m * mapImpl [K , V , C ]) Remove (key K ) {
103
+ compKey := m .conv (key )
104
+ delete (m .kv , compKey )
82
105
for i , k := range m .o {
83
- if k == key {
106
+ if m . conv ( k ) == compKey {
84
107
m .o = append (m .o [:i ], m .o [i + 1 :]... )
85
108
return
86
109
}
@@ -89,62 +112,44 @@ func (m *Map[K, V]) Remove(key K) {
89
112
90
113
// Merge merges other Maps into this one. Each key/value of the merged Maps replaces
91
114
// the key/value present in the original Map.
92
- func (m * Map [K , V ]) Merge (sources ... * Map [K , V ]) * Map [K , V ] {
115
+ func (m * mapImpl [K , V , C ]) Merge (sources ... Map [K , V ]) Map [K , V ] {
93
116
for _ , source := range sources {
94
- for _ , key := range source .o {
95
- value := source .kv [ key ]
117
+ for _ , key := range source .Keys () {
118
+ value := source .Get ( key )
96
119
m .Set (key , value )
97
120
}
98
121
}
99
122
return m
100
123
}
101
124
102
125
// Keys returns an array of the keys contained in the Map
103
- func (m * Map [K , V ]) Keys () []K {
126
+ func (m * mapImpl [K , V , C ]) Keys () []K {
104
127
keys := make ([]K , len (m .o ))
105
128
copy (keys , m .o )
106
129
return keys
107
130
}
108
131
109
- func (m * Map [K , V ]) SortKeys (f func (x , y K ) int ) {
132
+ func (m * mapImpl [K , V , C ]) SortKeys (f func (x , y K ) int ) {
110
133
slices .SortFunc (m .o , f )
111
134
}
112
135
113
- func (m * Map [K , V ]) SortStableKeys (f func (x , y K ) int ) {
136
+ func (m * mapImpl [K , V , C ]) SortStableKeys (f func (x , y K ) int ) {
114
137
slices .SortStableFunc (m .o , f )
115
138
}
116
139
117
140
// Values returns an array of the values contained in the Map. Duplicated
118
141
// values are repeated in the list accordingly.
119
- func (m * Map [K , V ]) Values () []V {
142
+ func (m * mapImpl [K , V , C ]) Values () []V {
120
143
values := make ([]V , len (m .o ))
121
144
for i , key := range m .o {
122
- values [i ] = m .kv [key ]
145
+ values [i ] = m .kv [m . conv ( key ) ]
123
146
}
124
147
return values
125
148
}
126
149
127
- // AsMap returns the underlying map[string]string. This is useful if you need to
128
- // for ... range but without the requirement of the ordered elements.
129
- func (m * Map [K , V ]) AsMap () map [K ]V {
130
- return m .kv
131
- }
132
-
133
150
// Clone makes a copy of the Map
134
- func (m * Map [K , V ]) Clone () * Map [K , V ] {
135
- clone := New [K , V ]( )
151
+ func (m * mapImpl [K , V , C ]) Clone () Map [K , V ] {
152
+ clone := NewWithConversionFunc [K , V , C ]( m . conv )
136
153
clone .Merge (m )
137
154
return clone
138
155
}
139
-
140
- // Equals returns true if the current Map contains the same key/value pairs of
141
- // the Map passed as argument, the order of insertion does not matter.
142
- func (m * Map [K , V ]) Equals (other * Map [K , V ]) bool {
143
- return reflect .DeepEqual (m .kv , other .kv )
144
- }
145
-
146
- // EqualsWithOrder returns true if the current Map contains the same key/value pairs of
147
- // the Map passed as argument with the same order of insertion.
148
- func (m * Map [K , V ]) EqualsWithOrder (other * Map [K , V ]) bool {
149
- return reflect .DeepEqual (m .o , other .o ) && reflect .DeepEqual (m .kv , other .kv )
150
- }
0 commit comments