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  }