Skip to content

Commit 9767ae7

Browse files
authored
Implement Go 1.23 iterators (#41)
Those are the Go 1.23 iterator that can be used with `for ... range`: https://go.dev/doc/go1.23#iterators.
1 parent f5ea9d1 commit 9767ae7

File tree

4 files changed

+89
-2
lines changed

4 files changed

+89
-2
lines changed

.github/workflows/ci.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@ on:
66

77
jobs:
88
unit-tests:
9+
strategy:
10+
matrix:
11+
go:
12+
- '=1.18'
13+
- '^1.23'
914
runs-on: ubuntu-latest
1015
steps:
1116
- uses: actions/checkout@v3
1217
- uses: actions/setup-go@v3
1318
with:
14-
go-version: '>=1.18.0'
15-
- run: go test
19+
go-version: ${{ matrix.go }}
20+
- run: go test -v ./...
21+
- run: cd v2 && go test -v ./...

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,20 @@ for el := m.Back(); el != nil; el = el.Prev() {
5252
}
5353
```
5454

55+
In case you're using Go 1.23, you can also [iterate with
56+
`range`](https://go.dev/doc/go1.23#iterators) by using `Iterator()` or
57+
`ReverseIterator()` methods:
58+
59+
```go
60+
for key, value := range m.Iterator() {
61+
fmt.Println(key, value)
62+
}
63+
64+
for key, value := range m.ReverseIterator() {
65+
fmt.Println(key, value)
66+
}
67+
```
68+
5569
The iterator is safe to use bidirectionally, and will return `nil` once it goes
5670
beyond the first or last item.
5771

v2/iterator.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//go:build go1.23
2+
// +build go1.23
3+
4+
package orderedmap
5+
6+
import "iter"
7+
8+
func (m *OrderedMap[K, V]) Iterator() iter.Seq2[K, V] {
9+
return func(yield func(key K, value V) bool) {
10+
for el := m.Front(); el != nil; el = el.Next() {
11+
if !yield(el.Key, el.Value) {
12+
return
13+
}
14+
}
15+
}
16+
}
17+
18+
func (m *OrderedMap[K, V]) ReverseIterator() iter.Seq2[K, V] {
19+
return func(yield func(key K, value V) bool) {
20+
for el := m.Back(); el != nil; el = el.Prev() {
21+
if !yield(el.Key, el.Value) {
22+
return
23+
}
24+
}
25+
}
26+
}

v2/iterator_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//go:build go1.23
2+
// +build go1.23
3+
4+
package orderedmap_test
5+
6+
import (
7+
"testing"
8+
9+
"github.com/elliotchance/orderedmap/v2"
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestIterators(t *testing.T) {
14+
type Element struct {
15+
Key int
16+
Value bool
17+
}
18+
m := orderedmap.NewOrderedMap[int, bool]()
19+
expected := []Element{{5, true}, {3, false}, {1, false}, {4, true}}
20+
for _, v := range expected {
21+
m.Set(v.Key, v.Value)
22+
}
23+
24+
t.Run("Iterator", func(t *testing.T) {
25+
i := 0
26+
for key, value := range m.Iterator() {
27+
assert.Equal(t, expected[i].Key, key)
28+
assert.Equal(t, expected[i].Value, value)
29+
i++
30+
}
31+
})
32+
33+
t.Run("ReverseIterator", func(t *testing.T) {
34+
i := len(expected) - 1
35+
for key, value := range m.ReverseIterator() {
36+
assert.Equal(t, expected[i].Key, key)
37+
assert.Equal(t, expected[i].Value, value)
38+
i--
39+
}
40+
})
41+
}

0 commit comments

Comments
 (0)