1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
|
// Copyright (c) 2018, Maxime Soulé
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree.
package tdutil
import (
"reflect"
"sort"
"github.com/maxatome/go-testdeep/internal/visited"
)
// MapSortedKeys returns a slice of all sorted keys of map m. It
// panics if m's [reflect.Kind] is not [reflect.Map].
func MapSortedKeys(m reflect.Value) []reflect.Value {
ks := m.MapKeys()
sort.Sort(SortableValues(ks))
return ks
}
type kv struct {
key reflect.Value
value reflect.Value
}
type kvSlice struct {
v visited.Visited
s []kv
}
func newKvSlice(l int) *kvSlice {
s := kvSlice{}
if l > 0 {
s.s = make([]kv, 0, l)
if l > 1 {
s.v = visited.NewVisited()
}
}
return &s
}
func (s *kvSlice) Len() int { return len(s.s) }
func (s *kvSlice) Less(i, j int) bool {
return cmp(s.v, s.s[i].key, s.s[j].key) < 0
}
func (s *kvSlice) Swap(i, j int) { s.s[i], s.s[j] = s.s[j], s.s[i] }
// MapEach calls fn for each key/value pair of map m. If fn
// returns false, it will not be called again.
func MapEach(m reflect.Value, fn func(k, v reflect.Value) bool) bool {
kvs := newKvSlice(m.Len())
iter := m.MapRange()
for iter.Next() {
kvs.s = append(kvs.s, kv{key: iter.Key(), value: iter.Value()})
}
sort.Sort(kvs)
for _, kv := range kvs.s {
if !fn(kv.key, kv.value) {
return false
}
}
return true
}
// MapEachValue calls fn for each value of map m. If fn returns
// false, it will not be called again.
func MapEachValue(m reflect.Value, fn func(k reflect.Value) bool) bool {
iter := m.MapRange()
for iter.Next() {
if !fn(iter.Value()) {
return false
}
}
return true
}
// MapSortedValues returns a slice of all sorted values of map m. It
// panics if m's [reflect.Kind] is not [reflect.Map].
func MapSortedValues(m reflect.Value) []reflect.Value {
vs := make([]reflect.Value, 0, m.Len())
iter := m.MapRange()
for iter.Next() {
vs = append(vs, iter.Value())
}
sort.Sort(SortableValues(vs))
return vs
}
|