github.com/searKing/golang/go@v1.2.117/exp/maps/spilt.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  // Split slices s into all submaps separated by sep and returns a slice of
     8  // the submaps between those separators.
     9  //
    10  // If s is less than sep and sep is more than zero, Split returns a
    11  // slice of length 1 whose only element is s.
    12  //
    13  // If s is nil, Split returns nil (zero submaps).
    14  //
    15  // If both s and sep are empty or zero, Split returns an empty slice.
    16  //
    17  // If sep is <= zero, Split splits after each element, as chunk size is 1.
    18  //
    19  // It is equivalent to SplitN with a count of -1.
    20  func Split[M ~map[K]V, K comparable, V any](m M, sep int) []M {
    21  	return SplitN(m, sep, -1)
    22  }
    23  
    24  // SplitN slices s into submaps and returns a slice of the submaps.
    25  //
    26  // The count determines the number of submaps to return:
    27  //
    28  //	  n > 0: at most n submaps; the last submaps will be the unsplit remainder.
    29  //			The count determines the number of submaps to return:
    30  //	  		sep > 0: Split splits every sep as chunk size; the last submaps will be the unsplit remainder.
    31  //	  		sep <= 0: take len(S)/n as chunk size
    32  //	  n == 0: the result is nil (zero submaps)
    33  //	  n < 0: all submaps as n == len(s)
    34  //
    35  // Edge cases for s and sep (for example, zero) are handled
    36  // as described in the documentation for Split.
    37  func SplitN[M ~map[K]V, K comparable, V any](m M, sep int, n int) []M {
    38  	// n < 0: all submaps as n == len(s)
    39  	if n < 0 {
    40  		n = len(m)
    41  	}
    42  	// Below: n >= 0
    43  
    44  	// n == 0: the result is nil (zero submaps)
    45  	// If s is nil, Split returns nil (zero submaps).
    46  	if n == 0 || m == nil {
    47  		return nil
    48  	}
    49  
    50  	// Below: s != nil && n > 0
    51  
    52  	// If both s and sep are empty or zero, Split returns an empty slice.
    53  	if len(m) == 0 && sep == 0 {
    54  		return []M{}
    55  	}
    56  
    57  	// If s is less or equal than sep and sep is more than zero, Split returns a
    58  	// slice of length 1 whose only element is s.
    59  	if len(m) <= sep && sep > 0 {
    60  		return []M{m}
    61  	}
    62  
    63  	// Below: len(s) > 0 && len(s) > sep && n > 0
    64  
    65  	// n > 0: at most n submaps; the last submaps will be the unsplit remainder.
    66  	//      The count determines the number of submaps to return:
    67  	//      sep > 0: Split splits every sep as chunk size; the last submaps will be the unsplit remainder.
    68  	//	  	sep <= 0: take len(S)/n as chunk size
    69  
    70  	if n == 1 || len(m) == 1 {
    71  		return []M{m}
    72  	}
    73  
    74  	// Below: len(s) > 1 && len(s) > sep && n > 1
    75  
    76  	// If sep is <= zero, Split splits after each element, as chunk size is 1.
    77  	chunkSize := len(m) / n
    78  	if chunkSize == 0 {
    79  		chunkSize = 1
    80  	}
    81  	if sep > 0 {
    82  		chunkSize = sep
    83  	}
    84  	var chunks []M
    85  	var chunk = make(M)
    86  	for k, v := range m {
    87  		if len(chunks) == n-1 || chunkSize > len(m) {
    88  			chunkSize = len(m)
    89  		}
    90  		if len(chunk) < chunkSize {
    91  			chunk[k] = v
    92  		}
    93  		if len(chunk) == chunkSize {
    94  			chunks = append(chunks, chunk)
    95  			chunk = make(M)
    96  		}
    97  	}
    98  	if len(chunk) > 0 {
    99  		chunks = append(chunks, chunk)
   100  	}
   101  	return chunks
   102  }