From 6bec2bd287c70d31f719e6c2979d1ab5c81935a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tighearn=C3=A1n=20Carroll?= Date: Tue, 22 Aug 2023 01:07:52 +0100 Subject: [PATCH 1/3] add range func --- orderedmap.go | 9 ++++++ orderedmap_test.go | 71 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/orderedmap.go b/orderedmap.go index 61587d9..711c76f 100644 --- a/orderedmap.go +++ b/orderedmap.go @@ -76,6 +76,15 @@ func (o *OrderedMap) Delete(key string) { delete(o.values, key) } +func (o *OrderedMap) Range(f func(key string, value interface{}) bool) { + for _, k := range o.keys { + v := o.values[k] + if !f(k, v) { + break + } + } +} + func (o *OrderedMap) Keys() []string { return o.keys } diff --git a/orderedmap_test.go b/orderedmap_test.go index 5b89ef6..abf0127 100644 --- a/orderedmap_test.go +++ b/orderedmap_test.go @@ -69,10 +69,10 @@ func TestOrderedMap(t *testing.T) { // Values method values := o.Values() expectedValues := map[string]interface{}{ - "number": 4, - "string": "x", + "number": 4, + "string": "x", "strings": []string{"t", "u"}, - "mixed": []interface{}{ 1, "1" }, + "mixed": []interface{}{1, "1"}, } if !reflect.DeepEqual(values, expectedValues) { t.Error("Values method returned unexpected map") @@ -595,3 +595,68 @@ func TestOrderedMap_empty_map(t *testing.T) { t.Error("Got", marshalledStr) } } + +func TestOrderedMap_Range(t *testing.T) { + tests := map[string]struct { + in []struct { + k string + v int + } + out []int + rangeFunc func(k string, v interface{}) bool + }{ + "test full range": { + in: []struct { + k string + v int + }{ + {k: "hello", v: 1}, + {k: "there", v: 2}, + {k: "outlier", v: 567}, + {k: "wow", v: 4}, + }, + out: []int{1, 2, 567, 4}, + }, + "test range with break": { + in: []struct { + k string + v int + }{ + {k: "hello", v: 1}, + {k: "there", v: 2}, + {k: "outlier", v: 567}, + {k: "wow", v: 4}, + }, + out: []int{1, 2, 567}, + rangeFunc: func(k string, v interface{}) bool { + return k != "outlier" + }, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + o := New() + + for _, p := range test.in { + o.Set(p.k, p.v) + } + + var out []int + o.Range(func(k string, v interface{}) bool { + i, ok := v.(int) + if !ok { + t.Errorf("%q is not an int. got=%v", k, v) + } + + out = append(out, i) + + if test.rangeFunc != nil { + return test.rangeFunc(k, v) + } + + return true + }) + }) + } +} From 2e63e4f8c13fa838660f38607578edb01e3b3af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tighearn=C3=A1n=20Carroll?= Date: Tue, 22 Aug 2023 01:12:09 +0100 Subject: [PATCH 2/3] comment --- orderedmap.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/orderedmap.go b/orderedmap.go index 711c76f..33a5d93 100644 --- a/orderedmap.go +++ b/orderedmap.go @@ -76,6 +76,9 @@ func (o *OrderedMap) Delete(key string) { delete(o.values, key) } +// Range over the ordered map, accessing entries in the same order they were +// added, making the traversal deterministic. +// This API is based on the api `sync.Map.Range`. func (o *OrderedMap) Range(f func(key string, value interface{}) bool) { for _, k := range o.keys { v := o.values[k] From 9762ac772b6c285de30dfb6fe413865948c61498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tighearn=C3=A1n=20Carroll?= Date: Tue, 22 Aug 2023 01:17:41 +0100 Subject: [PATCH 3/3] clarify usage --- orderedmap.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/orderedmap.go b/orderedmap.go index 33a5d93..7936e9e 100644 --- a/orderedmap.go +++ b/orderedmap.go @@ -79,10 +79,16 @@ func (o *OrderedMap) Delete(key string) { // Range over the ordered map, accessing entries in the same order they were // added, making the traversal deterministic. // This API is based on the api `sync.Map.Range`. -func (o *OrderedMap) Range(f func(key string, value interface{}) bool) { +// +// Provide a call function, `fn`, which will receive the key and value of each +// iteration. The callback function returns a bool indicating whether or not to +// continue looping. +// `true`: continue iteration +// `false`: break from interation +func (o *OrderedMap) Range(fn func(key string, value interface{}) bool) { for _, k := range o.keys { v := o.values[k] - if !f(k, v) { + if !fn(k, v) { break } }