github.com/gogf/gf/v2@v2.7.4/util/gutil/gutil_slice.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gutil
     8  
     9  import (
    10  	"reflect"
    11  
    12  	"github.com/gogf/gf/v2/util/gconv"
    13  )
    14  
    15  // SliceCopy does a shallow copy of slice `data` for most commonly used slice type
    16  // []interface{}.
    17  func SliceCopy(slice []interface{}) []interface{} {
    18  	newSlice := make([]interface{}, len(slice))
    19  	copy(newSlice, slice)
    20  	return newSlice
    21  }
    22  
    23  // SliceInsertBefore inserts the `values` to the front of `index` and returns a new slice.
    24  func SliceInsertBefore(slice []interface{}, index int, values ...interface{}) (newSlice []interface{}) {
    25  	if index < 0 || index >= len(slice) {
    26  		return slice
    27  	}
    28  	newSlice = make([]interface{}, len(slice)+len(values))
    29  	copy(newSlice, slice[0:index])
    30  	copy(newSlice[index:], values)
    31  	copy(newSlice[index+len(values):], slice[index:])
    32  	return
    33  }
    34  
    35  // SliceInsertAfter inserts the `values` to the back of `index` and returns a new slice.
    36  func SliceInsertAfter(slice []interface{}, index int, values ...interface{}) (newSlice []interface{}) {
    37  	if index < 0 || index >= len(slice) {
    38  		return slice
    39  	}
    40  	newSlice = make([]interface{}, len(slice)+len(values))
    41  	copy(newSlice, slice[0:index+1])
    42  	copy(newSlice[index+1:], values)
    43  	copy(newSlice[index+1+len(values):], slice[index+1:])
    44  	return
    45  }
    46  
    47  // SliceDelete deletes an element at `index` and returns the new slice.
    48  // It does nothing if the given `index` is invalid.
    49  func SliceDelete(slice []interface{}, index int) (newSlice []interface{}) {
    50  	if index < 0 || index >= len(slice) {
    51  		return slice
    52  	}
    53  	// Determine array boundaries when deleting to improve deletion efficiency.
    54  	if index == 0 {
    55  		return slice[1:]
    56  	} else if index == len(slice)-1 {
    57  		return slice[:index]
    58  	}
    59  	// If it is a non-boundary delete,
    60  	// it will involve the creation of an array,
    61  	// then the deletion is less efficient.
    62  	return append(slice[:index], slice[index+1:]...)
    63  }
    64  
    65  // SliceToMap converts slice type variable `slice` to `map[string]interface{}`.
    66  // Note that if the length of `slice` is not an even number, it returns nil.
    67  // Eg:
    68  // ["K1", "v1", "K2", "v2"] => {"K1": "v1", "K2": "v2"}
    69  // ["K1", "v1", "K2"]       => nil
    70  func SliceToMap(slice interface{}) map[string]interface{} {
    71  	var (
    72  		reflectValue = reflect.ValueOf(slice)
    73  		reflectKind  = reflectValue.Kind()
    74  	)
    75  	for reflectKind == reflect.Ptr {
    76  		reflectValue = reflectValue.Elem()
    77  		reflectKind = reflectValue.Kind()
    78  	}
    79  	switch reflectKind {
    80  	case reflect.Slice, reflect.Array:
    81  		length := reflectValue.Len()
    82  		if length%2 != 0 {
    83  			return nil
    84  		}
    85  		data := make(map[string]interface{})
    86  		for i := 0; i < reflectValue.Len(); i += 2 {
    87  			data[gconv.String(reflectValue.Index(i).Interface())] = reflectValue.Index(i + 1).Interface()
    88  		}
    89  		return data
    90  	}
    91  	return nil
    92  }
    93  
    94  // SliceToMapWithColumnAsKey converts slice type variable `slice` to `map[interface{}]interface{}`
    95  // The value of specified column use as the key for returned map.
    96  // Eg:
    97  // SliceToMapWithColumnAsKey([{"K1": "v1", "K2": 1}, {"K1": "v2", "K2": 2}], "K1") => {"v1": {"K1": "v1", "K2": 1}, "v2": {"K1": "v2", "K2": 2}}
    98  // SliceToMapWithColumnAsKey([{"K1": "v1", "K2": 1}, {"K1": "v2", "K2": 2}], "K2") => {1: {"K1": "v1", "K2": 1}, 2: {"K1": "v2", "K2": 2}}
    99  func SliceToMapWithColumnAsKey(slice interface{}, key interface{}) map[interface{}]interface{} {
   100  	var (
   101  		reflectValue = reflect.ValueOf(slice)
   102  		reflectKind  = reflectValue.Kind()
   103  	)
   104  	for reflectKind == reflect.Ptr {
   105  		reflectValue = reflectValue.Elem()
   106  		reflectKind = reflectValue.Kind()
   107  	}
   108  	data := make(map[interface{}]interface{})
   109  	switch reflectKind {
   110  	case reflect.Slice, reflect.Array:
   111  		for i := 0; i < reflectValue.Len(); i++ {
   112  			if k, ok := ItemValue(reflectValue.Index(i), key); ok {
   113  				data[k] = reflectValue.Index(i).Interface()
   114  			}
   115  		}
   116  	}
   117  	return data
   118  }