• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

enetx / g / 21095106390

17 Jan 2026 01:34PM UTC coverage: 90.189% (-0.04%) from 90.23%
21095106390

push

github

enetx
refactor(entry): redesign Entry API with Occupied/Vacant pattern

BREAKING CHANGE: Entry API completely redesigned

- Replace single MapEntry/MapOrdEntry/MapSafeEntry structs with
  sealed interfaces and Occupied/Vacant implementations:
  * Entry[K,V] interface with OccupiedEntry and VacantEntry
  * OrdEntry[K,V] interface with OccupiedOrdEntry and VacantOrdEntry
  * SafeEntry[K,V] interface with OccupiedSafeEntry and VacantSafeEntry

- Move entry implementations to dedicated files:
  * entry.go, entry_ordered.go, entry_safe.go

- Add MapSafe.TrySet() method for conditional insert (insert-if-absent)

- Update parallel iterators (Slice, Deque, Heap) to use TrySet
  instead of Entry().OrSet() for Unique operations

- Fix f.Match to properly handle []byte using regexp.Match()
  instead of converting to string

- Consolidate examples into entry.go

162 of 186 new or added lines in 12 files covered. (87.1%)

14 existing lines in 6 files now uncovered.

6499 of 7206 relevant lines covered (90.19%)

311.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.62
/map_ordered.go
1
package g
2

3
import (
4
        "fmt"
5
        "math/rand/v2"
6
        "slices"
7

8
        "github.com/enetx/g/cmp"
9
        "github.com/enetx/g/f"
10
)
11

12
// NewMapOrd creates a new ordered Map with the specified size (if provided).
13
// An ordered Map is an Map that maintains the order of its key-value pairs based on the
14
// insertion order. If no size is provided, the default size will be used.
15
//
16
// Parameters:
17
//
18
// - size ...int: (Optional) The initial size of the ordered Map. If not provided, a default size
19
// will be used.
20
//
21
// Returns:
22
//
23
// - MapOrd[K, V]: Ordered Map with the specified initial size (or default
24
// size if not provided).
25
//
26
// Example usage:
27
//
28
//        mapOrd := g.NewMapOrd[string, int](10)
29
//
30
// Creates a new ordered Map with an initial size of 10.
31
func NewMapOrd[K comparable, V any](size ...Int) MapOrd[K, V] {
216✔
32
        return make(MapOrd[K, V], 0, Slice[Int](size).Get(0).UnwrapOrDefault())
216✔
33
}
216✔
34

35
// Transform applies a transformation function to the MapOrd and returns the result.
36
func (mo MapOrd[K, V]) Transform(fn func(MapOrd[K, V]) MapOrd[K, V]) MapOrd[K, V] { return fn(mo) }
2✔
37

38
// Entry returns an OrdEntry for the given key.
39
func (mo *MapOrd[K, V]) Entry(key K) OrdEntry[K, V] {
45✔
40
        if i := mo.index(key); i != -1 {
66✔
41
                return OccupiedOrdEntry[K, V]{mo: mo, key: key, index: i}
21✔
42
        }
21✔
43

44
        return VacantOrdEntry[K, V]{mo: mo, key: key}
24✔
45
}
46

47
// Iter returns an iterator (SeqMapOrd[K, V]) for the ordered Map, allowing for sequential iteration
48
// over its key-value pairs. It is commonly used in combination with higher-order functions,
49
// such as 'ForEach', to perform operations on each key-value pair of the ordered Map.
50
//
51
// Returns:
52
//
53
// A SeqMapOrd[K, V], which can be used for sequential iteration over the key-value pairs of the ordered Map.
54
//
55
// Example usage:
56
//
57
//        m := g.NewMapOrd[int, int]()
58
//        m.Set(1, 1)
59
//        m.Set(2, 2)
60
//        m.Set(3, 3).
61
//
62
//        m.Iter().ForEach(func(k, v int) {
63
//            // Process key-value pair
64
//        })
65
//
66
// The 'Iter' method provides a convenient way to traverse the key-value pairs of an ordered Map
67
// in a functional style, enabling operations like mapping or filtering.
68
func (mo MapOrd[K, V]) Iter() SeqMapOrd[K, V] {
80✔
69
        return func(yield func(K, V) bool) {
165✔
70
                for _, v := range mo {
292✔
71
                        if !yield(v.Key, v.Value) {
224✔
72
                                return
17✔
73
                        }
17✔
74
                }
75
        }
76
}
77

78
// IterReverse returns an iterator (SeqMapOrd[K, V]) for the ordered Map that allows for sequential iteration
79
// over its key-value pairs in reverse order. This method is useful when you need to process the elements
80
// from the last to the first.
81
//
82
// Returns:
83
//
84
// A SeqMapOrd[K, V], which can be used for sequential iteration over the key-value pairs of the ordered Map in reverse order.
85
//
86
// Example usage:
87
//
88
//        m := g.NewMapOrd[int, int]()
89
//        m.Set(1, 1)
90
//        m.Set(2, 2)
91
//        m.Set(3, 3)
92
//
93
//        m.IterReverse().ForEach(func(k, v int) {
94
//            // Process key-value pair in reverse order
95
//            fmt.Println("Key:", k, "Value:", v)
96
//        })
97
//
98
// The 'IterReverse' method complements the 'Iter' method by providing a way to access the elements
99
// in a reverse sequence, offering additional flexibility in data processing scenarios.
100
func (mo MapOrd[K, V]) IterReverse() SeqMapOrd[K, V] {
4✔
101
        return func(yield func(K, V) bool) {
8✔
102
                for i := len(mo) - 1; i >= 0; i-- {
8✔
103
                        v := mo[i]
4✔
104
                        if !yield(v.Key, v.Value) {
4✔
105
                                return
×
106
                        }
×
107
                }
108
        }
109
}
110

111
// MapOrdFromStd converts a standard Go map to an ordered Map.
112
// The resulting ordered Map will maintain the order of its key-value pairs based on the order of
113
// insertion.
114
// This function is useful when you want to create an ordered Map from an existing Go map.
115
//
116
// Parameters:
117
//
118
// - m map[K]V: The input Go map to be converted to an ordered Map.
119
//
120
// Returns:
121
//
122
// - MapOrd[K, V]: New ordered Map containing the same key-value pairs as the
123
// input Go map.
124
//
125
// Example usage:
126
//
127
//        mapOrd := g.MapOrdFromStd[string, int](goMap)
128
//
129
// Converts the standard Go map 'map[K]V' to an ordered Map.
130
func MapOrdFromStd[K comparable, V any](m map[K]V) MapOrd[K, V] { return Map[K, V](m).ToMapOrd() }
2✔
131

132
// SortBy sorts the ordered Map by a custom comparison function.
133
//
134
// Parameters:
135
//
136
// - fn func(a, b Pair[K, V]) cmp.Ordering: The custom comparison function used for sorting the ordered Map.
137
//
138
// Example usage:
139
//
140
//        hmapo.SortBy(func(a, b g.Pair[g.String, g.Int]) cmp.Ordering { return a.Key.Cmp(b.Key) })
141
//        hmapo.SortBy(func(a, b g.Pair[g.String, g.Int]) cmp.Ordering { return a.Value.Cmp(b.Value) })
142
func (mo MapOrd[K, V]) SortBy(fn func(a, b Pair[K, V]) cmp.Ordering) {
3✔
143
        slices.SortFunc(mo, func(a, b Pair[K, V]) int { return int(fn(a, b)) })
12✔
144
}
145

146
// SortByKey sorts the ordered MapOrd[K, V] by the keys using a custom comparison function.
147
//
148
// Parameters:
149
//
150
// - fn func(a, b K) cmp.Ordering: The custom comparison function used for sorting the keys.
151
//
152
// Example usage:
153
//
154
//        hmapo.SortByKey(func(a, b g.String) cmp.Ordering { return a.Cmp(b) })
155
func (mo MapOrd[K, V]) SortByKey(fn func(a, b K) cmp.Ordering) {
6✔
156
        slices.SortFunc(mo, func(a, b Pair[K, V]) int { return int(fn(a.Key, b.Key)) })
35✔
157
}
158

159
// SortByValue sorts the ordered MapOrd[K, V] by the values using a custom comparison function.
160
//
161
// Parameters:
162
//
163
// - fn func(a, b V) cmp.Ordering: The custom comparison function used for sorting the values.
164
//
165
// Example usage:
166
//
167
//        hmapo.SortByValue(func(a, b g.Int) cmp.Ordering { return a.Cmp(b) })
168
func (mo MapOrd[K, V]) SortByValue(fn func(a, b V) cmp.Ordering) {
2✔
169
        slices.SortFunc(mo, func(a, b Pair[K, V]) int { return int(fn(a.Value, b.Value)) })
7✔
170
}
171

172
// IsSortedBy checks if the ordered Map is sorted according to a custom comparison function.
173
//
174
// Parameters:
175
//
176
// - fn func(a, b Pair[K, V]) cmp.Ordering: The custom comparison function used for checking sort order.
177
//
178
// Returns:
179
//
180
// - bool: true if the map is sorted according to the comparison function, false otherwise.
181
//
182
// Example usage:
183
//
184
//        sorted := hmapo.IsSortedBy(func(a, b g.Pair[g.String, g.Int]) cmp.Ordering { return a.Key.Cmp(b.Key) })
185
func (mo MapOrd[K, V]) IsSortedBy(fn func(a, b Pair[K, V]) cmp.Ordering) bool {
4✔
186
        if len(mo) <= 1 {
6✔
187
                return true
2✔
188
        }
2✔
189

190
        for i := 1; i < len(mo); i++ {
5✔
191
                if fn(mo[i-1], mo[i]).IsGt() {
4✔
192
                        return false
1✔
193
                }
1✔
194
        }
195

196
        return true
1✔
197
}
198

199
// IsSortedByKey checks if the ordered MapOrd[K, V] is sorted by the keys using a custom comparison function.
200
//
201
// Parameters:
202
//
203
// - fn func(a, b K) cmp.Ordering: The custom comparison function used for checking key sort order.
204
//
205
// Returns:
206
//
207
// - bool: true if the map is sorted by keys according to the comparison function, false otherwise.
208
//
209
// Example usage:
210
//
211
//        sorted := hmapo.IsSortedByKey(func(a, b g.String) cmp.Ordering { return a.Cmp(b) })
212
func (mo MapOrd[K, V]) IsSortedByKey(fn func(a, b K) cmp.Ordering) bool {
6✔
213
        if len(mo) <= 1 {
8✔
214
                return true
2✔
215
        }
2✔
216

217
        for i := 1; i < len(mo); i++ {
10✔
218
                if fn(mo[i-1].Key, mo[i].Key).IsGt() {
8✔
219
                        return false
2✔
220
                }
2✔
221
        }
222

223
        return true
2✔
224
}
225

226
// IsSortedByValue checks if the ordered MapOrd[K, V] is sorted by the values using a custom comparison function.
227
//
228
// Parameters:
229
//
230
// - fn func(a, b V) cmp.Ordering: The custom comparison function used for checking value sort order.
231
//
232
// Returns:
233
//
234
// - bool: true if the map is sorted by values according to the comparison function, false otherwise.
235
//
236
// Example usage:
237
//
238
//        sorted := hmapo.IsSortedByValue(func(a, b g.Int) cmp.Ordering { return a.Cmp(b) })
239
func (mo MapOrd[K, V]) IsSortedByValue(fn func(a, b V) cmp.Ordering) bool {
6✔
240
        if len(mo) <= 1 {
8✔
241
                return true
2✔
242
        }
2✔
243

244
        for i := 1; i < len(mo); i++ {
10✔
245
                if fn(mo[i-1].Value, mo[i].Value).IsGt() {
8✔
246
                        return false
2✔
247
                }
2✔
248
        }
249

250
        return true
2✔
251
}
252

253
// Clone creates a new ordered Map with the same key-value pairs.
254
func (mo MapOrd[K, V]) Clone() MapOrd[K, V] {
4✔
255
        nmo := NewMapOrd[K, V](mo.Len())
4✔
256
        nmo.Copy(mo)
4✔
257

4✔
258
        return nmo
4✔
259
}
4✔
260

261
// Copy copies key-value pairs from the source ordered Map to the current ordered Map.
262
func (mo *MapOrd[K, V]) Copy(src MapOrd[K, V]) {
6✔
263
        idx := mo.indexMap()
6✔
264

6✔
265
        for _, p := range src {
18✔
266
                if i, ok := idx[p.Key]; ok {
12✔
267
                        (*mo)[i].Value = p.Value
×
268
                } else {
12✔
269
                        *mo = append(*mo, p)
12✔
270
                        idx[p.Key] = len(*mo) - 1
12✔
271
                }
12✔
272
        }
273
}
274

275
// ToMap converts the ordered Map to a standard Map.
276
func (mo MapOrd[K, V]) ToMap() Map[K, V] {
×
277
        m := NewMap[K, V](mo.Len())
×
278
        mo.Iter().ForEach(func(k K, v V) { m[k] = v })
×
279

280
        return m
×
281
}
282

283
// ToMapSafe converts a ordered Map to a thread-safe Map.
284
func (mo MapOrd[K, V]) ToMapSafe() *MapSafe[K, V] {
×
285
        ms := NewMapSafe[K, V]()
×
286
        mo.Iter().ForEach(func(k K, v V) { ms.Set(k, v) })
×
287

288
        return ms
×
289
}
290

291
// Set sets the value for the specified key in the ordered Map,
292
// and returns the previous value if it existed.
293
func (mo *MapOrd[K, V]) Set(key K, value V) Option[V] {
468✔
294
        if i := mo.index(key); i != -1 {
476✔
295
                prev := (*mo)[i].Value
8✔
296
                (*mo)[i].Value = value
8✔
297

8✔
298
                return Some(prev)
8✔
299
        }
8✔
300

301
        mp := Pair[K, V]{Key: key, Value: value}
460✔
302
        *mo = append(*mo, mp)
460✔
303

460✔
304
        return None[V]()
460✔
305
}
306

307
// Get returns the value associated with the given key, wrapped in Option[V].
308
//
309
// It returns Some(value) if the key exists, or None if it does not.
310
func (mo MapOrd[K, V]) Get(key K) Option[V] {
37✔
311
        if i := mo.index(key); i != -1 {
74✔
312
                return Some(mo[i].Value)
37✔
313
        }
37✔
314

UNCOV
315
        return None[V]()
×
316
}
317

318
// Shuffle randomly reorders the elements of the ordered Map.
319
// It operates in place and affects the original order of the map's entries.
320
//
321
// The function uses the crypto/rand package to generate random indices.
322
func (mo MapOrd[K, V]) Shuffle() {
1✔
323
        for i := mo.Len() - 1; i > 0; i-- {
5✔
324
                j := rand.N(i + 1)
4✔
325
                mo[i], mo[j] = mo[j], mo[i]
4✔
326
        }
4✔
327
}
328

329
// Invert inverts the key-value pairs in the ordered Map, creating a new ordered Map with the
330
// values as keys and the original keys as values.
331
func (mo MapOrd[K, V]) Invert() MapOrd[any, K] {
2✔
332
        if mo.Empty() {
3✔
333
                return NewMapOrd[any, K]()
1✔
334
        }
1✔
335

336
        result := make(MapOrd[any, K], 0, len(mo))
1✔
337
        for _, pair := range mo {
4✔
338
                result = append(result, Pair[any, K]{Key: pair.Value, Value: pair.Key})
3✔
339
        }
3✔
340

341
        return result
1✔
342
}
343

344
func (mo MapOrd[K, V]) index(key K) int {
559✔
345
        for i, mp := range mo {
1,230✔
346
                if mp.Key == key {
743✔
347
                        return i
72✔
348
                }
72✔
349
        }
350

351
        return -1
487✔
352
}
353

354
// Keys returns an Slice containing all the keys in the ordered Map.
355
func (mo MapOrd[K, V]) Keys() Slice[K] { return mo.Iter().Keys().Collect() }
9✔
356

357
// Values returns an Slice containing all the values in the ordered Map.
358
func (mo MapOrd[K, V]) Values() Slice[V] { return mo.Iter().Values().Collect() }
2✔
359

360
// Delete removes the specified keys from the ordered Map.
361
//
362
// It preserves the original insertion order of the remaining elements
363
// and performs the deletion in a single pass with O(n) complexity.
364
//
365
// Internally, it builds a set of keys to delete and reconstructs the map
366
// without the removed entries. Key lookup is optimized via a map[K]int index.
367
//
368
// Example:
369
//
370
//        mo.Delete("a", "b", "c")
371
func (mo *MapOrd[K, V]) Delete(keys ...K) {
5✔
372
        if len(keys) == 0 || mo.Empty() {
6✔
373
                return
1✔
374
        }
1✔
375

376
        idx := mo.indexMap()
4✔
377
        seen := SetOf(keys...)
4✔
378
        nmo := make(MapOrd[K, V], 0, len(*mo)-min(len(keys), len(*mo)))
4✔
379

4✔
380
        for _, p := range *mo {
15✔
381
                if !seen.Contains(p.Key) {
17✔
382
                        nmo = append(nmo, p)
6✔
383
                } else {
11✔
384
                        delete(idx, p.Key)
5✔
385
                }
5✔
386
        }
387

388
        *mo = nmo
4✔
389
}
390

391
// Eq compares the current ordered Map to another ordered Map and returns true if they are equal.
392
func (mo MapOrd[K, V]) Eq(other MapOrd[K, V]) bool {
30✔
393
        if len(mo) != len(other) {
32✔
394
                return false
2✔
395
        }
2✔
396
        if len(mo) == 0 {
31✔
397
                return true
3✔
398
        }
3✔
399

400
        idx := other.indexMap()
25✔
401

25✔
402
        var zero V
25✔
403
        comparable := f.IsComparable(zero)
25✔
404

25✔
405
        for i, mp := range mo {
94✔
406
                j, ok := idx[mp.Key]
69✔
407
                if !ok || j != i {
70✔
408
                        return false
1✔
409
                }
1✔
410

411
                value := other[j].Value
68✔
412

68✔
413
                if comparable && !f.Eq[any](value)(mp.Value) || !comparable && !f.Eqd(value)(mp.Value) {
69✔
414
                        return false
1✔
415
                }
1✔
416
        }
417

418
        return true
23✔
419
}
420

421
// String returns a string representation of the ordered Map.
422
func (mo MapOrd[K, V]) String() string {
5✔
423
        if len(mo) == 0 {
6✔
424
                return "MapOrd{}"
1✔
425
        }
1✔
426

427
        var b Builder
4✔
428
        b.WriteString("MapOrd{")
4✔
429

4✔
430
        first := true
4✔
431
        for _, pair := range mo {
12✔
432
                if !first {
12✔
433
                        b.WriteString(", ")
4✔
434
                }
4✔
435

436
                first = false
8✔
437
                b.WriteString(Format("{}:{}", pair.Key, pair.Value))
8✔
438
        }
439

440
        b.WriteString("}")
4✔
441

4✔
442
        return b.String().Std()
4✔
443
}
444

445
// Clear removes all key-value pairs from the ordered Map.
446
func (mo *MapOrd[K, V]) Clear() { *mo = (*mo)[:0] }
2✔
447

448
// Contains checks if the ordered Map contains the specified key.
449
func (mo MapOrd[K, V]) Contains(key K) bool { return mo.index(key) != -1 }
9✔
450

451
// Empty checks if the ordered Map is empty.
452
func (mo MapOrd[K, V]) Empty() bool { return len(mo) == 0 }
13✔
453

454
// Len returns the number of key-value pairs in the ordered Map.
455
func (mo MapOrd[K, V]) Len() Int { return Int(len(mo)) }
29✔
456

457
// Ne compares the current ordered Map to another ordered Map and returns true if they are not equal.
458
func (mo MapOrd[K, V]) Ne(other MapOrd[K, V]) bool { return !mo.Eq(other) }
8✔
459

460
// NotEmpty checks if the ordered Map is not empty.
461
func (mo MapOrd[K, V]) NotEmpty() bool { return !mo.Empty() }
2✔
462

463
// Print writes the key-value pairs of the MapOrd to the standard output (console)
464
// and returns the MapOrd unchanged.
465
func (mo MapOrd[K, V]) Print() MapOrd[K, V] { fmt.Print(mo); return mo }
1✔
466

467
// Println writes the key-value pairs of the MapOrd to the standard output (console) with a newline
468
// and returns the MapOrd unchanged.
469
func (mo MapOrd[K, V]) Println() MapOrd[K, V] { fmt.Println(mo); return mo }
1✔
470

471
// indexMap builds a map from keys to their corresponding indices in the MapOrd.
472
//
473
// This function is used to create a temporary indexMap that maps each key in the
474
// ordered map to its position (insertion order) within the slice. It is useful
475
// for optimizing lookup operations such as Set, Delete, Copy, or Eq.
476
//
477
// Time complexity: O(n), where n is the number of key-value pairs in the MapOrd.
478
func (mo MapOrd[K, V]) indexMap() map[K]int {
35✔
479
        idx := make(map[K]int, len(mo))
35✔
480

35✔
481
        for i, p := range mo {
123✔
482
                idx[p.Key] = i
88✔
483
        }
88✔
484

485
        return idx
35✔
486
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc