github.com/searKing/golang/go@v1.2.117/exp/maps/filter.go (about) 1 // Copyright 2022 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package maps 6 7 import "reflect" 8 9 // Filter returns a map satisfying c != zero within all c in the map. 10 // Filter modifies the contents of the map s; it does not create a new map. 11 func Filter[M ~map[K]V, K comparable, V comparable](m M) M { 12 if len(m) == 0 { 13 return m 14 } 15 for k, v := range m { 16 var zeroV V 17 if v == zeroV { 18 delete(m, k) 19 } 20 } 21 return m 22 } 23 24 // FilterFunc returns a map satisfying f(c) within all c in the map. 25 // FilterFunc modifies the contents of the map s; it does not create a new map. 26 func FilterFunc[M ~map[K]V, K comparable, V any](m M, f func(K, V) bool) M { 27 if len(m) == 0 { 28 return m 29 } 30 for k, v := range m { 31 if !f(k, v) { 32 delete(m, k) 33 } 34 } 35 return m 36 } 37 38 // TypeAssertFilter returns a map satisfying r, ok := any(c).(R); ok == true within all r in the map. 39 // TypeAssertFilter does not modify the contents of the map m; it creates a new map. 40 func TypeAssertFilter[M ~map[K]V, M2 ~map[K2]V2, K comparable, V comparable, K2 comparable, V2 comparable](m M) M2 { 41 if len(m) == 0 { 42 if m == nil { 43 return nil 44 } 45 var emptyM2 = M2{} 46 return emptyM2 47 } 48 49 var m2 = M2{} 50 51 var zeroK K 52 var zeroV V 53 var zeroK2 K2 54 var zeroV2 V2 55 var nilableK = any(zeroK) == nil 56 var nilableV = any(zeroV) == nil 57 58 var k2t = reflect.TypeOf(zeroK2) 59 var v2t = reflect.TypeOf(zeroV2) 60 var convertibleK bool 61 var convertibleV bool 62 if !nilableK || any(zeroK) != nil { 63 var et = reflect.TypeOf(zeroK) 64 convertibleK = et.ConvertibleTo(k2t) 65 } 66 if !nilableV || any(zeroV) != nil { 67 var et = reflect.TypeOf(zeroV) 68 convertibleV = et.ConvertibleTo(v2t) 69 } 70 71 for k, v := range m { 72 if !convertibleK && !nilableK { 73 continue 74 } 75 if !convertibleV && !nilableV { 76 continue 77 } 78 79 if (any(k) == nil && any(zeroK2) == nil) && (any(v) == nil && any(zeroV2) == nil) { 80 var zeroK2 K2 81 var zeroV2 V2 82 m2[zeroK2] = zeroV2 83 continue 84 } 85 86 if k2, ok := any(k).(K2); ok { 87 if v2, ok := any(v).(V2); ok { 88 m2[k2] = v2 89 continue 90 } 91 } 92 if convertibleK && convertibleV { 93 if k2, ok := reflect.ValueOf(k).Convert(k2t).Interface().(K2); ok { 94 if v2, ok := reflect.ValueOf(v).Convert(v2t).Interface().(V2); ok { 95 m2[k2] = v2 96 continue 97 } 98 } 99 } 100 } 101 return m2 102 } 103 104 // TypeAssertFilterFunc returns a map satisfying f(c) within all c in the map. 105 // TypeAssertFilterFunc does not modify the contents of the map m; it creates a new map. 106 func TypeAssertFilterFunc[M ~map[K]V, M2 ~map[K2]V2, K comparable, V any, K2 comparable, V2 any](m M, f func(K, V) (K2, V2, bool)) M2 { 107 if len(m) == 0 { 108 if m == nil { 109 return nil 110 } 111 var emptyM2 = M2{} 112 return emptyM2 113 } 114 115 var m2 = M2{} 116 for k, v := range m { 117 if k, v, ok := f(k, v); ok { 118 m2[k] = v 119 } 120 } 121 return m2 122 }