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  }