Skip to content

Commit 019e1aa

Browse files
author
Tom Godkin
committed
Implement LiftHashMapKeys and LiftHashMapValues
1 parent ab781dd commit 019e1aa

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed

iter/lift.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,81 @@ func (iter *LiftHashMapIter[T, U]) Next() option.Option[Tuple[T, U]] {
9191
}
9292

9393
var _ Iterator[Tuple[struct{}, struct{}]] = new(LiftHashMapIter[struct{}, struct{}])
94+
95+
// LiftHashMapKeysIter implements `LiftHashMapKeys`. See `LiftHashMapKeys`'
96+
// documentation.
97+
type LiftHashMapKeysIter[T comparable, U any] struct {
98+
delegate *LiftHashMapIter[T, U]
99+
delegateMap *MapIter[Tuple[T, U], T]
100+
exhausted bool
101+
}
102+
103+
// LiftHashMapKeys instantiates a `LiftHashMapKeysIter` that will yield all
104+
// keys in the provided map.
105+
//
106+
// See documentation on `LiftHashMap` for information on closing this iterator.
107+
func LiftHashMapKeys[T comparable, U any](hashmap map[T]U) *LiftHashMapKeysIter[T, U] {
108+
delegate := LiftHashMap(hashmap)
109+
110+
return &LiftHashMapKeysIter[T, U]{delegate, Map[Tuple[T, U]](delegate, func(pair Tuple[T, U]) T { return pair.One }), false}
111+
}
112+
113+
// Close the iterator. See `LiftHashMapKeys` documentation for details.
114+
func (iter *LiftHashMapKeysIter[T, U]) Close() {
115+
iter.delegate.Close()
116+
}
117+
118+
// Next implements the Iterator interface for `LiftHashMapKeys`.
119+
func (iter *LiftHashMapKeysIter[T, U]) Next() option.Option[T] {
120+
if iter.exhausted {
121+
return option.None[T]()
122+
}
123+
124+
next := iter.delegateMap.Next()
125+
if next.IsNone() {
126+
iter.exhausted = true
127+
}
128+
129+
return next
130+
}
131+
132+
var _ Iterator[struct{}] = new(LiftHashMapKeysIter[struct{}, struct{}])
133+
134+
// LiftHashMapValuesIter implements `LiftHashMapValues`. See
135+
// `LiftHashMapValues`' documentation.
136+
type LiftHashMapValuesIter[T comparable, U any] struct {
137+
delegate *LiftHashMapIter[T, U]
138+
delegateMap *MapIter[Tuple[T, U], U]
139+
exhausted bool
140+
}
141+
142+
// LiftHashMapValues instantiates a `LiftHashMapValuesIter` that will yield all
143+
// values in the provided map.
144+
//
145+
// See documentation on `LiftHashMap` for information on closing this iterator.
146+
func LiftHashMapValues[T comparable, U any](hashmap map[T]U) *LiftHashMapValuesIter[T, U] {
147+
delegate := LiftHashMap(hashmap)
148+
149+
return &LiftHashMapValuesIter[T, U]{delegate, Map[Tuple[T, U]](delegate, func(pair Tuple[T, U]) U { return pair.Two }), false}
150+
}
151+
152+
// Close the iterator. See `LiftHashMapKeys` documentation for details.
153+
func (iter *LiftHashMapValuesIter[T, U]) Close() {
154+
iter.delegate.Close()
155+
}
156+
157+
// Next implements the Iterator interface for `LiftHashMapValuesIter`.
158+
func (iter *LiftHashMapValuesIter[T, U]) Next() option.Option[U] {
159+
if iter.exhausted {
160+
return option.None[U]()
161+
}
162+
163+
next := iter.delegateMap.Next()
164+
if next.IsNone() {
165+
iter.exhausted = true
166+
}
167+
168+
return next
169+
}
170+
171+
var _ Iterator[struct{}] = new(LiftHashMapValuesIter[struct{}, struct{}])

iter/lift_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,87 @@ func TestLiftHashMapCloseAfterExhaustedSafe(t *testing.T) {
7070
iter.Collect[iter.Tuple[string, string]](items)
7171
items.Close()
7272
}
73+
74+
func TestLiftHashMapKeys(t *testing.T) {
75+
pokemon := make(map[string]string)
76+
pokemon["name"] = "pikachu"
77+
pokemon["type"] = "electric"
78+
79+
keys := iter.Collect[string](iter.LiftHashMapKeys(pokemon))
80+
sort.Strings(keys)
81+
82+
assert.SliceEqual(t, keys, []string{"name", "type"})
83+
}
84+
85+
func TestLiftHashMapKeysCloseEarly(t *testing.T) {
86+
pokemon := make(map[string]string)
87+
pokemon["name"] = "pikachu"
88+
pokemon["type"] = "electric"
89+
90+
items := iter.LiftHashMapKeys(pokemon)
91+
assert.True(t, items.Next().IsSome())
92+
items.Close()
93+
assert.True(t, items.Next().IsNone())
94+
}
95+
96+
func TestLiftHashMapKeysCloseMultipleSafe(t *testing.T) {
97+
pokemon := make(map[string]string)
98+
pokemon["name"] = "pikachu"
99+
pokemon["type"] = "electric"
100+
101+
items := iter.LiftHashMapKeys(pokemon)
102+
items.Close()
103+
items.Close()
104+
}
105+
106+
func TestLiftHashMapKeysCloseAfterExhaustedSafe(t *testing.T) {
107+
pokemon := make(map[string]string)
108+
pokemon["name"] = "pikachu"
109+
pokemon["type"] = "electric"
110+
111+
items := iter.LiftHashMapKeys(pokemon)
112+
iter.Collect[string](items)
113+
items.Close()
114+
}
115+
116+
func TestLiftHashMapValues(t *testing.T) {
117+
pokemon := make(map[string]string)
118+
pokemon["name"] = "pikachu"
119+
pokemon["type"] = "electric"
120+
121+
keys := iter.Collect[string](iter.LiftHashMapValues(pokemon))
122+
sort.Strings(keys)
123+
124+
assert.SliceEqual(t, keys, []string{"electric", "pikachu"})
125+
}
126+
127+
func TestLiftHashMapValuesCloseEarly(t *testing.T) {
128+
pokemon := make(map[string]string)
129+
pokemon["name"] = "pikachu"
130+
pokemon["type"] = "electric"
131+
132+
items := iter.LiftHashMapValues(pokemon)
133+
assert.True(t, items.Next().IsSome())
134+
items.Close()
135+
assert.True(t, items.Next().IsNone())
136+
}
137+
138+
func TestLiftHashMapValuesCloseMultipleSafe(t *testing.T) {
139+
pokemon := make(map[string]string)
140+
pokemon["name"] = "pikachu"
141+
pokemon["type"] = "electric"
142+
143+
items := iter.LiftHashMapValues(pokemon)
144+
items.Close()
145+
items.Close()
146+
}
147+
148+
func TestLiftHashMapValuesCloseAfterExhaustedSafe(t *testing.T) {
149+
pokemon := make(map[string]string)
150+
pokemon["name"] = "pikachu"
151+
pokemon["type"] = "electric"
152+
153+
items := iter.LiftHashMapValues(pokemon)
154+
iter.Collect[string](items)
155+
items.Close()
156+
}

0 commit comments

Comments
 (0)