github.com/searKing/golang/go@v1.2.117/exp/slices/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 slices 6 7 import "reflect" 8 9 // Filter returns a slice satisfying c != zero within all c in the slice. 10 // Filter modifies the contents of the slice s; it does not create a new slice. 11 func Filter[S ~[]E, E comparable](s S) S { 12 if len(s) == 0 { 13 return s 14 } 15 i := 0 16 for _, v := range s { 17 var zeroE E 18 if v != zeroE { 19 s[i] = v 20 i++ 21 } 22 } 23 return s[:i] 24 } 25 26 // FilterFunc returns a slice satisfying f(c) within all c in the slice. 27 // FilterFunc modifies the contents of the slice s; it does not create a new slice. 28 func FilterFunc[S ~[]E, E any](s S, f func(E) bool) S { 29 if len(s) == 0 { 30 return s 31 } 32 i := 0 33 for _, v := range s { 34 if f(v) { 35 s[i] = v 36 i++ 37 } 38 } 39 return s[:i] 40 } 41 42 // TypeAssertFilter returns a slice satisfying r, ok := any(c).(R); ok == true within all r in the slice. 43 // TypeAssertFilter does not modify the contents of the slice s; it creates a new slice. 44 func TypeAssertFilter[S ~[]E, M ~[]R, E any, R any](s S) M { 45 if len(s) == 0 { 46 if s == nil { 47 return nil 48 } 49 var emptyM = M{} 50 return emptyM 51 } 52 var m = M{} 53 54 var zeroE E 55 var zeroR R 56 var nilable = any(zeroE) == nil 57 58 var rt = reflect.TypeOf(zeroR) 59 var convertible bool 60 if !nilable || any(zeroE) != nil { 61 var et = reflect.TypeOf(zeroE) 62 convertible = et.ConvertibleTo(rt) 63 } 64 65 for _, v := range s { 66 if !convertible && !nilable { 67 continue 68 } 69 70 if any(v) == nil && any(zeroR) == nil { 71 var zeroR R 72 m = append(m, zeroR) 73 continue 74 } 75 76 if r, ok := any(v).(R); ok { 77 m = append(m, r) 78 continue 79 } 80 if convertible { 81 if r, ok := reflect.ValueOf(v).Convert(rt).Interface().(R); ok { 82 m = append(m, r) 83 continue 84 } 85 } 86 } 87 return m 88 } 89 90 // TypeAssertFilterFunc returns a slice satisfying f(c) within all c in the slice. 91 // TypeAssertFilterFunc does not modify the contents of the slice s; it creates a new slice. 92 func TypeAssertFilterFunc[S ~[]E, M ~[]R, E any, R any](s S, f func(E) (R, bool)) M { 93 if len(s) == 0 { 94 if s == nil { 95 return nil 96 } 97 var emptyM = M{} 98 return emptyM 99 } 100 101 var m = M{} 102 for _, v := range s { 103 if r, ok := f(v); ok { 104 m = append(m, r) 105 } 106 } 107 return m 108 }