github.com/gogf/gf@v1.16.9/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  	"github.com/gogf/gf/util/gconv"
    11  	"reflect"
    12  )
    13  
    14  // SliceCopy does a shallow copy of slice `data` for most commonly used slice type
    15  // []interface{}.
    16  func SliceCopy(data []interface{}) []interface{} {
    17  	newData := make([]interface{}, len(data))
    18  	copy(newData, data)
    19  	return newData
    20  }
    21  
    22  // SliceDelete deletes an element at `index` and returns the new slice.
    23  // It does nothing if the given `index` is invalid.
    24  func SliceDelete(data []interface{}, index int) (newSlice []interface{}) {
    25  	if index < 0 || index >= len(data) {
    26  		return data
    27  	}
    28  	// Determine array boundaries when deleting to improve deletion efficiency.
    29  	if index == 0 {
    30  		return data[1:]
    31  	} else if index == len(data)-1 {
    32  		return data[:index]
    33  	}
    34  	// If it is a non-boundary delete,
    35  	// it will involve the creation of an array,
    36  	// then the deletion is less efficient.
    37  	return append(data[:index], data[index+1:]...)
    38  }
    39  
    40  // SliceToMap converts slice type variable `slice` to `map[string]interface{}`.
    41  // Note that if the length of `slice` is not an even number, it returns nil.
    42  // Eg:
    43  // ["K1", "v1", "K2", "v2"] => {"K1": "v1", "K2": "v2"}
    44  // ["K1", "v1", "K2"]       => nil
    45  func SliceToMap(slice interface{}) map[string]interface{} {
    46  	var (
    47  		reflectValue = reflect.ValueOf(slice)
    48  		reflectKind  = reflectValue.Kind()
    49  	)
    50  	for reflectKind == reflect.Ptr {
    51  		reflectValue = reflectValue.Elem()
    52  		reflectKind = reflectValue.Kind()
    53  	}
    54  	switch reflectKind {
    55  	case reflect.Slice, reflect.Array:
    56  		length := reflectValue.Len()
    57  		if length%2 != 0 {
    58  			return nil
    59  		}
    60  		data := make(map[string]interface{})
    61  		for i := 0; i < reflectValue.Len(); i += 2 {
    62  			data[gconv.String(reflectValue.Index(i).Interface())] = reflectValue.Index(i + 1).Interface()
    63  		}
    64  		return data
    65  	}
    66  	return nil
    67  }
    68  
    69  // SliceToMapWithColumnAsKey converts slice type variable `slice` to `map[interface{}]interface{}`
    70  // The value of specified column use as the key for returned map.
    71  // Eg:
    72  // SliceToMapWithColumnAsKey([{"K1": "v1", "K2": 1}, {"K1": "v2", "K2": 2}], "K1") => {"v1": {"K1": "v1", "K2": 1}, "v2": {"K1": "v2", "K2": 2}}
    73  // SliceToMapWithColumnAsKey([{"K1": "v1", "K2": 1}, {"K1": "v2", "K2": 2}], "K2") => {1: {"K1": "v1", "K2": 1}, 2: {"K1": "v2", "K2": 2}}
    74  func SliceToMapWithColumnAsKey(slice interface{}, key interface{}) map[interface{}]interface{} {
    75  	var (
    76  		reflectValue = reflect.ValueOf(slice)
    77  		reflectKind  = reflectValue.Kind()
    78  	)
    79  	for reflectKind == reflect.Ptr {
    80  		reflectValue = reflectValue.Elem()
    81  		reflectKind = reflectValue.Kind()
    82  	}
    83  	data := make(map[interface{}]interface{})
    84  	switch reflectKind {
    85  	case reflect.Slice, reflect.Array:
    86  		for i := 0; i < reflectValue.Len(); i++ {
    87  			if k, ok := ItemValue(reflectValue.Index(i), key); ok {
    88  				data[k] = reflectValue.Index(i).Interface()
    89  			}
    90  		}
    91  	}
    92  	return data
    93  }