github.com/jxskiss/gopkg@v0.17.3/easy/slice.go (about)

     1  package easy
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"strconv"
     7  	"strings"
     8  	"unsafe"
     9  
    10  	"github.com/jxskiss/gopkg/internal/unsafeheader"
    11  	"github.com/jxskiss/gopkg/reflectx"
    12  )
    13  
    14  const (
    15  	maxInsertGrowth = 1024
    16  )
    17  
    18  //nolint:unused
    19  const (
    20  	errNotSliceType           = "not slice type"
    21  	errNotSliceOfInt          = "not a slice of integers"
    22  	errElemTypeNotMatchSlice  = "elem type does not match slice"
    23  	errElemNotStructOrPointer = "elem is not struct or pointer to struct"
    24  	errStructFieldNotProvided = "struct field is not provided"
    25  	errStructFieldNotExists   = "struct field not exists"
    26  	errStructFieldIsNotInt    = "struct field is not integer or pointer"
    27  	errStructFieldIsNotStr    = "struct field is not string or pointer"
    28  )
    29  
    30  func panicNilParams(where string, params ...interface{}) {
    31  	for i := 0; i < len(params); i += 2 {
    32  		arg := params[i].(string)
    33  		val := params[i+1]
    34  		if val == nil {
    35  			panic(fmt.Sprintf("%s: param %s is nil interface", where, arg))
    36  		}
    37  	}
    38  }
    39  
    40  func assertSliceOfIntegers(where string, sliceTyp reflect.Type) {
    41  	if sliceTyp.Kind() != reflect.Slice || !reflectx.IsIntType(sliceTyp.Elem().Kind()) {
    42  		panic(where + ":" + errNotSliceOfInt)
    43  	}
    44  }
    45  
    46  func assertSliceAndElemType(where string, sliceVal reflect.Value, elemTyp reflect.Type) (reflect.Value, bool) {
    47  	if sliceVal.Kind() != reflect.Slice {
    48  		panic(where + ": " + errNotSliceType)
    49  	}
    50  	intTypeNotMatch := false
    51  	sliceTyp := sliceVal.Type()
    52  	if elemTyp != sliceTyp.Elem() {
    53  		// int-family
    54  		if reflectx.IsIntType(sliceTyp.Elem().Kind()) &&
    55  			reflectx.IsIntType(elemTyp.Kind()) {
    56  			intTypeNotMatch = true
    57  		} else {
    58  			panic(where + ": " + errElemTypeNotMatchSlice)
    59  		}
    60  	}
    61  	return sliceVal, intTypeNotMatch
    62  }
    63  
    64  func assertSliceElemStructAndField(where string, sliceTyp reflect.Type, field string) reflect.StructField {
    65  	if field == "" {
    66  		panic(where + ": " + errStructFieldNotProvided)
    67  	}
    68  	if sliceTyp.Kind() != reflect.Slice {
    69  		panic(where + ": " + errNotSliceType)
    70  	}
    71  	elemTyp := sliceTyp.Elem()
    72  	elemIsPtr := elemTyp.Kind() == reflect.Ptr
    73  	if !(elemTyp.Kind() == reflect.Struct ||
    74  		(elemIsPtr && elemTyp.Elem().Kind() == reflect.Struct)) {
    75  		panic(where + ": " + errElemNotStructOrPointer)
    76  	}
    77  	var fieldInfo reflect.StructField
    78  	var ok bool
    79  	if elemIsPtr {
    80  		fieldInfo, ok = elemTyp.Elem().FieldByName(field)
    81  	} else {
    82  		fieldInfo, ok = elemTyp.FieldByName(field)
    83  	}
    84  	if !ok {
    85  		panic(where + ": " + errStructFieldNotExists)
    86  	}
    87  	return fieldInfo
    88  }
    89  
    90  // InSlice is reserved for a generic implementation.
    91  
    92  // InSliceFunc iterates the given slice, it calls predicate(i) for i in range [0, n)
    93  // where n is the length of the slice.
    94  // When predicate(i) returns true, it stops and returns true.
    95  //
    96  // The parameter predicate must be not nil, otherwise it panics.
    97  func InSliceFunc(slice interface{}, predicate func(i int) bool) bool {
    98  	if slice == nil {
    99  		return false
   100  	}
   101  	sliceTyp := reflect.TypeOf(slice)
   102  	if sliceTyp.Kind() != reflect.Slice {
   103  		panic("InSliceFunc: " + errNotSliceType)
   104  	}
   105  	_, header := reflectx.UnpackSlice(slice)
   106  	for i := 0; i < header.Len; i++ {
   107  		if predicate(i) {
   108  			return true
   109  		}
   110  	}
   111  	return false
   112  }
   113  
   114  // InInt32s tells whether the int32 value elem is in the slice.
   115  func InInt32s(slice []int32, elem int32) bool {
   116  	for _, x := range slice {
   117  		if x == elem {
   118  			return true
   119  		}
   120  	}
   121  	return false
   122  }
   123  
   124  // InInt64s tells whether the int64 value elem is in the slice.
   125  func InInt64s(slice []int64, elem int64) bool {
   126  	for _, x := range slice {
   127  		if x == elem {
   128  			return true
   129  		}
   130  	}
   131  	return false
   132  }
   133  
   134  // InStrings tells whether the string value elem is in the slice.
   135  func InStrings(slice []string, elem string) bool {
   136  	for _, x := range slice {
   137  		if elem == x {
   138  			return true
   139  		}
   140  	}
   141  	return false
   142  }
   143  
   144  // Index is reserved for a generic implementation.
   145  
   146  // IndexFunc iterates the given slice, it calls predicate(i) for i in
   147  // range [0, n) where n is the length of the slice.
   148  // When predicate(i) returns true, it stops and returns the index i.
   149  //
   150  // The parameter predicate must not be nil, otherwise it panics.
   151  func IndexFunc(slice interface{}, predicate func(i int) bool) int {
   152  	if slice == nil {
   153  		return -1
   154  	}
   155  	sliceTyp := reflect.TypeOf(slice)
   156  	if sliceTyp.Kind() != reflect.Slice {
   157  		panic("IndexFunc: " + errNotSliceType)
   158  	}
   159  	_, header := reflectx.UnpackSlice(slice)
   160  	for i := 0; i < header.Len; i++ {
   161  		if predicate(i) {
   162  			return i
   163  		}
   164  	}
   165  	return -1
   166  }
   167  
   168  // IndexInt32s returns the index of the first instance of elem slice,
   169  // or -1 if elem is not present in slice.
   170  func IndexInt32s(slice []int32, elem int32) int {
   171  	for i := 0; i < len(slice); i++ {
   172  		if elem == slice[i] {
   173  			return i
   174  		}
   175  	}
   176  	return -1
   177  }
   178  
   179  // IndexInt64s returns the index of the first instance of elem in slice,
   180  // or -1 if elem is not present in slice.
   181  func IndexInt64s(slice []int64, elem int64) int {
   182  	for i := 0; i < len(slice); i++ {
   183  		if elem == slice[i] {
   184  			return i
   185  		}
   186  	}
   187  	return -1
   188  }
   189  
   190  // IndexStrings returns the index of the first instance of elem in slice,
   191  // or -1 if elem is not present in slice.
   192  func IndexStrings(slice []string, elem string) int {
   193  	for i := 0; i < len(slice); i++ {
   194  		if elem == slice[i] {
   195  			return i
   196  		}
   197  	}
   198  	return -1
   199  }
   200  
   201  // LastIndex is reserved for a generic implementation.
   202  
   203  // LastIndexFunc iterates the given slice, it calls predicate(i) for i in
   204  // range [0, n) in descending order, where n is the length of the slice.
   205  // When predicate(i) returns true, it stops and returns the index i.
   206  //
   207  // The parameter predicate must not be nil, otherwise it panics.
   208  func LastIndexFunc(slice interface{}, predicate func(i int) bool) int {
   209  	if slice == nil {
   210  		return -1
   211  	}
   212  	sliceTyp := reflect.TypeOf(slice)
   213  	if sliceTyp.Kind() != reflect.Slice {
   214  		panic("LastIndexFunc: " + errNotSliceType)
   215  	}
   216  	_, header := reflectx.UnpackSlice(slice)
   217  	for i := header.Len - 1; i >= 0; i-- {
   218  		if predicate(i) {
   219  			return i
   220  		}
   221  	}
   222  	return -1
   223  }
   224  
   225  // LastIndexInt32s returns the index of the last instance of elem in slice,
   226  // or -1 if elem is not present in slice.
   227  func LastIndexInt32s(slice []int32, elem int32) int {
   228  	for i := len(slice) - 1; i >= 0; i-- {
   229  		if elem == slice[i] {
   230  			return i
   231  		}
   232  	}
   233  	return -1
   234  }
   235  
   236  // LastIndexInt64s returns the index of the last instance of elem in slice,
   237  // or -1 if elem is not present in slice.
   238  func LastIndexInt64s(slice []int64, elem int64) int {
   239  	for i := len(slice) - 1; i >= 0; i-- {
   240  		if elem == slice[i] {
   241  			return i
   242  		}
   243  	}
   244  	return -1
   245  }
   246  
   247  // LastIndexStrings returns the index of the last instance of elem in slice,
   248  // or -1 if elem is not present in slice.
   249  func LastIndexStrings(slice []string, elem string) int {
   250  	for i := len(slice) - 1; i >= 0; i-- {
   251  		if elem == slice[i] {
   252  			return i
   253  		}
   254  	}
   255  	return -1
   256  }
   257  
   258  // InsertSlice is reserved for a generic implementation.
   259  
   260  // InsertInt32s inserts the given int32 elem into the slice at index position.
   261  // If index is equal or greater than the length of slice, the elem will be
   262  // appended to the end of the slice. In case the slice is full of it's
   263  // capacity, a new slice will be created and returned.
   264  func InsertInt32s(slice []int32, index int, elem int32) (out []int32) {
   265  	if index >= len(slice) {
   266  		return append(slice, elem)
   267  	}
   268  	oldLen := len(slice)
   269  	if len(slice) == cap(slice) {
   270  		// capacity not enough, grow the slice
   271  		newCap := oldLen + min(max(1, oldLen), maxInsertGrowth)
   272  		out = make([]int32, oldLen+1, newCap)
   273  		copy(out, slice[:index])
   274  	} else {
   275  		out = slice[:oldLen+1]
   276  	}
   277  	copy(out[index+1:], slice[index:])
   278  	out[index] = elem
   279  	return
   280  }
   281  
   282  // InsertInt64s inserts the given int64 elem into the slice at index position.
   283  // If index is equal or greater than the length of slice, the elem will be
   284  // appended to the end of the slice. In case the slice is full of it's
   285  // capacity, a new slice will be created and returned.
   286  func InsertInt64s(slice []int64, index int, elem int64) (out []int64) {
   287  	if index >= len(slice) {
   288  		return append(slice, elem)
   289  	}
   290  	oldLen := len(slice)
   291  	if len(slice) == cap(slice) {
   292  		// capacity not enough, grow the slice
   293  		newCap := oldLen + min(max(1, oldLen), maxInsertGrowth)
   294  		out = make([]int64, oldLen+1, newCap)
   295  		copy(out, slice[:index])
   296  	} else {
   297  		out = slice[:oldLen+1]
   298  	}
   299  	copy(out[index+1:], slice[index:])
   300  	out[index] = elem
   301  	return
   302  }
   303  
   304  // InsertStrings inserts the given string elem into the slice at index position.
   305  // If index is equal or greater than the length of slice, the elem will be
   306  // appended to the end of the slice. In case the slice is full of it's
   307  // capacity, a new slice will be created and returned.
   308  func InsertStrings(slice []string, index int, elem string) (out []string) {
   309  	if index >= len(slice) {
   310  		return append(slice, elem)
   311  	}
   312  	oldLen := len(slice)
   313  	if len(slice) == cap(slice) {
   314  		// capacity not enough, grow the slice
   315  		newCap := oldLen + min(max(1, oldLen), maxInsertGrowth)
   316  		out = make([]string, oldLen+1, newCap)
   317  		copy(out, slice[:index])
   318  	} else {
   319  		out = slice[:oldLen+1]
   320  	}
   321  	copy(out[index+1:], slice[index:])
   322  	out[index] = elem
   323  	return
   324  }
   325  
   326  // Reverse is reserved for a generic implementation.
   327  
   328  // ReverseSlice returns a new slice containing the elements of the given
   329  // slice in reversed order.
   330  //
   331  // When inplace is true, the slice is reversed in place, it does not create
   332  // a new slice, but returns the original slice with reversed order.
   333  //
   334  // The given slice must be not nil, otherwise it panics.
   335  func ReverseSlice(slice interface{}, inplace bool) interface{} {
   336  	if slice == nil {
   337  		panicNilParams("ReverseSlice", "slice", slice)
   338  	}
   339  	sliceTyp := reflect.TypeOf(slice)
   340  	if sliceTyp.Kind() != reflect.Slice {
   341  		panic("ReverseSlice: " + errNotSliceType)
   342  	}
   343  
   344  	_, srcHeader := reflectx.UnpackSlice(slice)
   345  	length := srcHeader.Len
   346  	elemTyp := sliceTyp.Elem()
   347  	elemRType := reflectx.ToRType(elemTyp)
   348  	elemSize := elemRType.Size()
   349  
   350  	outSlice, outHeader := slice, srcHeader
   351  	if !inplace {
   352  		outSlice, outHeader = reflectx.MakeSlice(elemTyp, length, length)
   353  		reflectx.TypedSliceCopy(elemRType, *outHeader, *srcHeader)
   354  	}
   355  	tmp := reflect.New(elemTyp).Elem().Interface()
   356  	swap := reflectx.EfaceOf(&tmp).Word
   357  	for i, mid := 0, length/2; i < mid; i++ {
   358  		j := length - i - 1
   359  		pi := reflectx.ArrayAt(outHeader.Data, i, elemSize)
   360  		pj := reflectx.ArrayAt(outHeader.Data, j, elemSize)
   361  		reflectx.TypedMemMove(elemRType, swap, pi)
   362  		reflectx.TypedMemMove(elemRType, pi, pj)
   363  		reflectx.TypedMemMove(elemRType, pj, swap)
   364  	}
   365  	return outSlice
   366  }
   367  
   368  // ReverseInt32s returns a new slice of the elements in reversed order.
   369  //
   370  // When inplace is true, the slice is reversed in place, it does not create
   371  // a new slice, but returns the original slice with reversed order.
   372  func ReverseInt32s(slice []int32, inplace bool) []int32 {
   373  	length := len(slice)
   374  	out := slice
   375  	if !inplace {
   376  		out = make([]int32, length)
   377  		copy(out, slice)
   378  	}
   379  	for i, mid := 0, length/2; i < mid; i++ {
   380  		j := length - i - 1
   381  		out[i], out[j] = out[j], out[i]
   382  	}
   383  	return out
   384  }
   385  
   386  // ReverseInt64s returns a new slice of the elements in reversed order.
   387  //
   388  // When inplace is true, the slice is reversed in place, it does not create
   389  // a new slice, but returns the original slice with reversed order.
   390  func ReverseInt64s(slice []int64, inplace bool) []int64 {
   391  	length := len(slice)
   392  	out := slice
   393  	if !inplace {
   394  		out = make([]int64, length)
   395  		copy(out, slice)
   396  	}
   397  	for i, mid := 0, length/2; i < mid; i++ {
   398  		j := length - i - 1
   399  		out[i], out[j] = out[j], out[i]
   400  	}
   401  	return out
   402  }
   403  
   404  // ReverseStrings returns a new slice of the elements in reversed order.
   405  //
   406  // When inplace is true, the slice is reversed in place, it does not create
   407  // a new slice, but returns the original slice with reversed order.
   408  func ReverseStrings(slice []string, inplace bool) []string {
   409  	length := len(slice)
   410  	out := slice
   411  	if !inplace {
   412  		out = make([]string, length)
   413  		copy(out, slice)
   414  	}
   415  	for i, mid := 0, length/2; i < mid; i++ {
   416  		j := length - i - 1
   417  		out[i], out[j] = out[j], out[i]
   418  	}
   419  	return out
   420  }
   421  
   422  // UniqueSlice is reserved for a generic implementation.
   423  
   424  // UniqueInt32s returns a new slice containing the elements of the given
   425  // slice in same order, but filter out duplicate values.
   426  //
   427  // When inplace is true, it does not create a new slice, the unique values
   428  // will be written to the input slice from the beginning.
   429  func UniqueInt32s(slice []int32, inplace bool) []int32 {
   430  	seen := make(map[int32]struct{})
   431  	out := slice[:0]
   432  	if !inplace {
   433  		out = make([]int32, 0)
   434  	}
   435  	for _, x := range slice {
   436  		if _, ok := seen[x]; ok {
   437  			continue
   438  		}
   439  		seen[x] = struct{}{}
   440  		out = append(out, x)
   441  	}
   442  	return out
   443  }
   444  
   445  // UniqueInt64s returns a new slice containing the elements of the given
   446  // slice in same order, but filter out duplicate values.
   447  //
   448  // When inplace is true, it does not create a new slice, the unique values
   449  // will be written to the input slice from the beginning.
   450  func UniqueInt64s(slice []int64, inplace bool) []int64 {
   451  	seen := make(map[int64]struct{})
   452  	out := slice[:0]
   453  	if !inplace {
   454  		out = make([]int64, 0)
   455  	}
   456  	for _, x := range slice {
   457  		if _, ok := seen[x]; ok {
   458  			continue
   459  		}
   460  		seen[x] = struct{}{}
   461  		out = append(out, x)
   462  	}
   463  	return out
   464  }
   465  
   466  // UniqueStrings returns a new slice containing the elements of the given
   467  // slice in same order, but filter out duplicate values.
   468  //
   469  // When inplace is true, it does not create a new slice, the unique values
   470  // will be written to the input slice from the beginning.
   471  func UniqueStrings(slice []string, inplace bool) []string {
   472  	seen := make(map[string]struct{})
   473  	out := slice[:0]
   474  	if !inplace {
   475  		out = make([]string, 0)
   476  	}
   477  	for _, x := range slice {
   478  		if _, ok := seen[x]; ok {
   479  			continue
   480  		}
   481  		seen[x] = struct{}{}
   482  		out = append(out, x)
   483  	}
   484  	return out
   485  }
   486  
   487  // DiffSlice is reserved for a generic implementation.
   488  
   489  // DiffInt32s returns a new int32 slice containing the values which present
   490  // in slice a but not present in slice b.
   491  func DiffInt32s(a []int32, b []int32) []int32 {
   492  	bset := make(map[int32]struct{}, len(b))
   493  	for _, x := range b {
   494  		bset[x] = struct{}{}
   495  	}
   496  	out := make([]int32, 0)
   497  	for _, x := range a {
   498  		if _, ok := bset[x]; !ok {
   499  			out = append(out, x)
   500  		}
   501  	}
   502  	return out
   503  }
   504  
   505  // DiffInt64s returns a new int64 slice containing the values which present
   506  // in slice a but not present in slice b.
   507  func DiffInt64s(a []int64, b []int64) []int64 {
   508  	bset := make(map[int64]struct{}, len(b))
   509  	for _, x := range b {
   510  		bset[x] = struct{}{}
   511  	}
   512  	out := make([]int64, 0)
   513  	for _, x := range a {
   514  		if _, ok := bset[x]; !ok {
   515  			out = append(out, x)
   516  		}
   517  	}
   518  	return out
   519  }
   520  
   521  // DiffStrings returns a new string slice containing the values which
   522  // present in slice a but not present in slice b.
   523  func DiffStrings(a []string, b []string) []string {
   524  	bset := make(map[string]struct{}, len(b))
   525  	for _, x := range b {
   526  		bset[x] = struct{}{}
   527  	}
   528  	out := make([]string, 0)
   529  	for _, x := range a {
   530  		if _, ok := bset[x]; !ok {
   531  			out = append(out, x)
   532  		}
   533  	}
   534  	return out
   535  }
   536  
   537  // ToMap converts the given slice of struct (or pointer to struct) to a map,
   538  // with the field specified by keyField as key and the slice element as value.
   539  //
   540  // If slice is nil, keyField does not exists or the element of slice is not
   541  // struct or pointer to struct, it panics.
   542  func ToMap(slice interface{}, keyField string) interface{} {
   543  	if slice == nil {
   544  		panicNilParams("ToMap", "slice", slice)
   545  	}
   546  	sliceVal := reflect.ValueOf(slice)
   547  	sliceTyp := sliceVal.Type()
   548  	fieldInfo := assertSliceElemStructAndField("ToMap", sliceTyp, keyField)
   549  	keyTyp := fieldInfo.Type
   550  	if keyTyp.Kind() == reflect.Ptr {
   551  		keyTyp = keyTyp.Elem()
   552  	}
   553  
   554  	elemTyp := sliceTyp.Elem()
   555  	outVal := reflect.MakeMapWithSize(reflect.MapOf(keyTyp, elemTyp), sliceVal.Len())
   556  	for i := 0; i < sliceVal.Len(); i++ {
   557  		elem := sliceVal.Index(i)
   558  		fieldVal := reflect.Indirect(reflect.Indirect(elem).FieldByName(keyField))
   559  		outVal.SetMapIndex(fieldVal, elem)
   560  	}
   561  	return outVal.Interface()
   562  }
   563  
   564  // ToSliceMap converts the given slice of struct (or pointer to struct) to a map,
   565  // with the field specified by keyField as key and a slice of elements which have
   566  // same key as value.
   567  //
   568  // If slice is nil, keyField does not exists or the element of slice is not
   569  // struct or pointer to struct, it panics.
   570  func ToSliceMap(slice interface{}, keyField string) interface{} {
   571  	if slice == nil {
   572  		panicNilParams("ToSliceMap", "slice", slice)
   573  	}
   574  	sliceVal := reflect.ValueOf(slice)
   575  	sliceTyp := sliceVal.Type()
   576  	fieldInfo := assertSliceElemStructAndField("ToSliceMap", sliceTyp, keyField)
   577  	keyTyp := fieldInfo.Type
   578  	if keyTyp.Kind() == reflect.Ptr {
   579  		keyTyp = keyTyp.Elem()
   580  	}
   581  
   582  	elemTyp := sliceTyp.Elem()
   583  	elemSliceTyp := reflect.SliceOf(elemTyp)
   584  	outVal := reflect.MakeMap(reflect.MapOf(keyTyp, elemSliceTyp))
   585  	for i := sliceVal.Len() - 1; i >= 0; i-- {
   586  		elem := sliceVal.Index(i)
   587  		fieldVal := reflect.Indirect(reflect.Indirect(elem).FieldByName(keyField))
   588  		elemSlice := outVal.MapIndex(fieldVal)
   589  		if !elemSlice.IsValid() {
   590  			elemSlice = reflect.MakeSlice(elemSliceTyp, 0, 1)
   591  		}
   592  		elemSlice = reflect.Append(elemSlice, elem)
   593  		outVal.SetMapIndex(fieldVal, elemSlice)
   594  	}
   595  	return outVal.Interface()
   596  }
   597  
   598  // ToMapMap converts the given slice of struct (or pointer to struct) to a map,
   599  // with the field specified by keyField as key.
   600  // The returned map's value is another map with the field specified by
   601  // subKeyField as key and thee slice element as value.
   602  //
   603  // If slice is nil, keyField or subKeyField does not exists or the element of
   604  // slice is not struct or pointer to struct, it panics.
   605  func ToMapMap(slice interface{}, keyField, subKeyField string) interface{} {
   606  	if slice == nil {
   607  		panicNilParams("ToMapMap", "slice", slice)
   608  	}
   609  	sliceVal := reflect.ValueOf(slice)
   610  	sliceTyp := sliceVal.Type()
   611  	fieldInfo1 := assertSliceElemStructAndField("ToMapMap", sliceTyp, keyField)
   612  	fieldInfo2 := assertSliceElemStructAndField("ToMapMap", sliceTyp, subKeyField)
   613  	keyTyp1 := fieldInfo1.Type
   614  	if keyTyp1.Kind() == reflect.Ptr {
   615  		keyTyp1 = keyTyp1.Elem()
   616  	}
   617  	keyTyp2 := fieldInfo2.Type
   618  	if keyTyp2.Kind() == reflect.Ptr {
   619  		keyTyp2 = keyTyp2.Elem()
   620  	}
   621  
   622  	elemTyp := sliceTyp.Elem()
   623  	elemMapTyp := reflect.MapOf(keyTyp2, elemTyp)
   624  	outVal := reflect.MakeMap(reflect.MapOf(keyTyp1, elemMapTyp))
   625  	for i := sliceVal.Len() - 1; i >= 0; i-- {
   626  		elem := sliceVal.Index(i)
   627  		fieldVal1 := reflect.Indirect(reflect.Indirect(elem).FieldByName(keyField))
   628  		fieldVal2 := reflect.Indirect(reflect.Indirect(elem).FieldByName(subKeyField))
   629  		elemMap := outVal.MapIndex(fieldVal1)
   630  		if !elemMap.IsValid() {
   631  			elemMap = reflect.MakeMap(elemMapTyp)
   632  			outVal.SetMapIndex(fieldVal1, elemMap)
   633  		}
   634  		elemMap.SetMapIndex(fieldVal2, elem)
   635  	}
   636  	return outVal.Interface()
   637  }
   638  
   639  // ToInterfaceSlice returns a []interface{} containing elements from slice.
   640  func ToInterfaceSlice(slice interface{}) []interface{} {
   641  	if slice == nil {
   642  		return nil
   643  	}
   644  	sliceTyp := reflect.TypeOf(slice)
   645  	if sliceTyp.Kind() != reflect.Slice {
   646  		panic("ToInterfaceSlice: " + errNotSliceType)
   647  	}
   648  	sliceVal := reflect.ValueOf(slice)
   649  	out := make([]interface{}, 0, sliceVal.Len())
   650  	for i := 0; i < sliceVal.Len(); i++ {
   651  		elem := sliceVal.Index(i).Interface()
   652  		out = append(out, elem)
   653  	}
   654  	return out
   655  }
   656  
   657  // Find is reserved for a generic implementation.
   658  
   659  // FindFunc returns the first element in the slice for which predicate returns true.
   660  func FindFunc(slice interface{}, predicate func(i int) bool) interface{} {
   661  	if slice == nil {
   662  		return nil
   663  	}
   664  	sliceTyp := reflect.TypeOf(slice)
   665  	if sliceTyp.Kind() != reflect.Slice {
   666  		panic("FindFunc: " + errNotSliceType)
   667  	}
   668  	_, header := reflectx.UnpackSlice(slice)
   669  	for i := 0; i < header.Len; i++ {
   670  		if predicate(i) {
   671  			return reflect.ValueOf(slice).Index(i).Interface()
   672  		}
   673  	}
   674  	return nil
   675  }
   676  
   677  // Filter is reserved for a generic implementation.
   678  
   679  // FilterFunc iterates the given slice, it calls predicate(i) for i in
   680  // range [0, n), where n is the length of the slice.
   681  // It returns a new slice of elements for which predicate(i) returns true.
   682  //
   683  // The parameter slice and predicate must not be nil, otherwise it panics.
   684  func FilterFunc(slice interface{}, predicate func(i int) bool) interface{} {
   685  	if slice == nil {
   686  		panicNilParams("FilterFunc", "slice", slice)
   687  	}
   688  	sliceTyp := reflect.TypeOf(slice)
   689  	if sliceTyp.Kind() != reflect.Slice {
   690  		panic("FilterFunc: " + errNotSliceType)
   691  	}
   692  
   693  	sliceVal := reflect.ValueOf(slice)
   694  	length := sliceVal.Len()
   695  	outVal := reflect.MakeSlice(sliceVal.Type(), 0, max(length/4+1, 4))
   696  	for i := 0; i < length; i++ {
   697  		if predicate(i) {
   698  			elem := sliceVal.Index(i)
   699  			outVal = reflect.Append(outVal, elem)
   700  		}
   701  	}
   702  	return outVal.Interface()
   703  }
   704  
   705  // FilterInt32s iterates the given slice, it calls predicate(i) for i in
   706  // range [0, n), where n is the length of the slice.
   707  // It returns a new slice of elements for which predicate(i) returns true.
   708  func FilterInt32s(slice []int32, predicate func(i int) bool) []int32 {
   709  	length := len(slice)
   710  	out := make([]int32, 0, max(length/4+1, 4))
   711  	for i := 0; i < length; i++ {
   712  		if predicate(i) {
   713  			out = append(out, slice[i])
   714  		}
   715  	}
   716  	return out
   717  }
   718  
   719  // FilterInt64s iterates the given slice, it calls predicate(i) for i in
   720  // range [0, n), where n is the length of the slice.
   721  // It returns a new slice of elements for which predicate(i) returns true.
   722  func FilterInt64s(slice []int64, predicate func(i int) bool) []int64 {
   723  	length := len(slice)
   724  	out := make([]int64, 0, max(length/4+1, 4))
   725  	for i := 0; i < length; i++ {
   726  		if predicate(i) {
   727  			out = append(out, slice[i])
   728  		}
   729  	}
   730  	return out
   731  }
   732  
   733  // FilterStrings iterates the given slice, it calls predicate(i) for i in
   734  // range [0, n), where n is the length of the slice.
   735  // It returns a new slice of elements for which predicate(i) returns true.
   736  func FilterStrings(slice []string, predicate func(i int) bool) []string {
   737  	length := len(slice)
   738  	out := make([]string, 0, max(length/4+1, 4))
   739  	for i := 0; i < length; i++ {
   740  		if predicate(i) {
   741  			out = append(out, slice[i])
   742  		}
   743  	}
   744  	return out
   745  }
   746  
   747  // SumSlice returns the sum value of the elements in the given slice.
   748  // If slice is nil or it's elements are not integers, it panics.
   749  func SumSlice(slice interface{}) int64 {
   750  	if slice == nil {
   751  		panicNilParams("SumSlice", "slice", slice)
   752  	}
   753  	sliceTyp := reflect.TypeOf(slice)
   754  	assertSliceOfIntegers("SumSlice", sliceTyp)
   755  
   756  	var sum int64
   757  	elemTyp := sliceTyp.Elem()
   758  	elemKind := elemTyp.Kind()
   759  	elemSize := elemTyp.Size()
   760  	_, header := reflectx.UnpackSlice(slice)
   761  	for i := 0; i < header.Len; i++ {
   762  		ptr := reflectx.ArrayAt(header.Data, i, elemSize)
   763  		sum += reflectx.CastIntPointer(elemKind, ptr)
   764  	}
   765  	return sum
   766  }
   767  
   768  // ParseInt64s parses a number string separated by sep into a []int64 slice.
   769  // If there is invalid number value, it reports malformed = true as the
   770  // second return value.
   771  func ParseInt64s(values, sep string, ignoreZero bool) (slice []int64, malformed bool) {
   772  	values = strings.TrimSpace(values)
   773  	values = strings.Trim(values, sep)
   774  	segments := strings.Split(values, sep)
   775  	slice = make([]int64, 0, len(segments))
   776  	for _, x := range segments {
   777  		id, err := strconv.ParseInt(x, 10, 64)
   778  		if err != nil {
   779  			malformed = true
   780  			continue
   781  		}
   782  		if id == 0 && ignoreZero {
   783  			continue
   784  		}
   785  		slice = append(slice, id)
   786  	}
   787  	return
   788  }
   789  
   790  // JoinInt64s returns a string consisting of slice elements separated by sep.
   791  func JoinInt64s(slice []int64, sep string) string {
   792  	if len(slice) == 0 {
   793  		return ""
   794  	}
   795  	if len(slice) == 1 {
   796  		return strconv.FormatInt(slice[0], 10)
   797  	}
   798  	var buf []byte
   799  	buf = strconv.AppendInt(buf, slice[0], 10)
   800  	for _, x := range slice[1:] {
   801  		buf = append(buf, sep...)
   802  		buf = strconv.AppendInt(buf, x, 10)
   803  	}
   804  	return unsafeheader.BytesToString(buf)
   805  }
   806  
   807  // IJ represents a slice index of I, J.
   808  type IJ struct{ I, J int }
   809  
   810  // SplitBatch splits a large number to batches, it's mainly designed to
   811  // help operations with large slice, such as inserting lots of records
   812  // into database, or logging lots of identifiers, etc.
   813  func SplitBatch(total, batch int) []IJ {
   814  	if total <= 0 {
   815  		return nil
   816  	}
   817  	if batch <= 0 {
   818  		return []IJ{{0, total}}
   819  	}
   820  	n := total/batch + 1
   821  	ret := make([]IJ, n)
   822  	idx := 0
   823  	for i, j := 0, batch; idx < n && i < total; i, j = i+batch, j+batch {
   824  		if j > total {
   825  			j = total
   826  		}
   827  		ret[idx] = IJ{i, j}
   828  		idx++
   829  	}
   830  	return ret[:idx]
   831  }
   832  
   833  // Split is reserved for a generic implementation.
   834  
   835  // SplitSlice splits a large slice []T to batches, it returns a slice
   836  // of slice of type [][]T.
   837  //
   838  // The given slice must not be nil, otherwise it panics.
   839  func SplitSlice(slice interface{}, batch int) interface{} {
   840  	if slice == nil {
   841  		panicNilParams("SplitSlice", "slice", slice)
   842  	}
   843  	sliceTyp := reflectx.RTypeOf(slice)
   844  	if sliceTyp.Kind() != reflect.Slice {
   845  		panic("SplitSlice: " + errNotSliceType)
   846  	}
   847  
   848  	_, sliceHeader := reflectx.UnpackSlice(slice)
   849  	indexes := SplitBatch(sliceHeader.Len, batch)
   850  	elemTyp := sliceTyp.Elem()
   851  	elemSize := elemTyp.Size()
   852  	out := make([]reflectx.SliceHeader, len(indexes))
   853  	for i, idx := range indexes {
   854  		subSlice := _takeSlice(sliceHeader.Data, elemSize, idx.I, idx.J)
   855  		out[i] = subSlice
   856  	}
   857  
   858  	outTyp := reflectx.SliceOf(sliceTyp)
   859  	return outTyp.PackInterface(unsafe.Pointer(&out))
   860  }
   861  
   862  func _takeSlice(base unsafe.Pointer, elemSize uintptr, i, j int) (slice reflectx.SliceHeader) {
   863  	if length := j - i; length > 0 {
   864  		slice.Data = reflectx.ArrayAt(base, i, elemSize)
   865  		slice.Len = length
   866  		slice.Cap = length
   867  	}
   868  	return
   869  }
   870  
   871  // SplitInt64s splits a large int64 slice to batches.
   872  func SplitInt64s(slice []int64, batch int) [][]int64 {
   873  	indexes := SplitBatch(len(slice), batch)
   874  	out := make([][]int64, len(indexes))
   875  	for i, idx := range indexes {
   876  		out[i] = slice[idx.I:idx.J]
   877  	}
   878  	return out
   879  }
   880  
   881  // SplitInt32s splits a large int32 slice to batches.
   882  func SplitInt32s(slice []int32, batch int) [][]int32 {
   883  	indexes := SplitBatch(len(slice), batch)
   884  	out := make([][]int32, len(indexes))
   885  	for i, idx := range indexes {
   886  		out[i] = slice[idx.I:idx.J]
   887  	}
   888  	return out
   889  }
   890  
   891  // SplitStrings splits a large string slice to batches.
   892  func SplitStrings(slice []string, batch int) [][]string {
   893  	indexes := SplitBatch(len(slice), batch)
   894  	out := make([][]string, len(indexes))
   895  	for i, idx := range indexes {
   896  		out[i] = slice[idx.I:idx.J]
   897  	}
   898  	return out
   899  }
   900  
   901  func isIntTypeOrPtr(typ reflect.Type) bool {
   902  	if reflectx.IsIntType(typ.Kind()) ||
   903  		(typ.Kind() == reflect.Ptr && reflectx.IsIntType(typ.Elem().Kind())) {
   904  		return true
   905  	}
   906  	return false
   907  }
   908  
   909  func isStringTypeOrPtr(typ reflect.Type) bool {
   910  	return typ.Kind() == reflect.String ||
   911  		(typ.Kind() == reflect.Ptr && typ.Elem().Kind() == reflect.String)
   912  }
   913  
   914  func min(a, b int) int {
   915  	if a < b {
   916  		return a
   917  	}
   918  	return b
   919  }
   920  
   921  func max(a, b int) int {
   922  	if a > b {
   923  		return a
   924  	}
   925  	return b
   926  }