github.com/webx-top/com@v1.2.12/slice.go (about)

     1  // Copyright 2013 com authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"): you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    12  // License for the specific language governing permissions and limitations
    13  // under the License.
    14  
    15  package com
    16  
    17  import (
    18  	"errors"
    19  	"math/rand"
    20  	"reflect"
    21  	"sort"
    22  	"strings"
    23  	"time"
    24  )
    25  
    26  func WithPrefix(strs []string, prefix string) []string {
    27  	for k, v := range strs {
    28  		strs[k] = prefix + v
    29  	}
    30  	return strs
    31  }
    32  
    33  func WithSuffix(strs []string, suffix string) []string {
    34  	for k, v := range strs {
    35  		strs[k] = v + suffix
    36  	}
    37  	return strs
    38  }
    39  
    40  // AppendStr appends string to slice with no duplicates.
    41  func AppendStr(strs []string, str string) []string {
    42  	for _, s := range strs {
    43  		if s == str {
    44  			return strs
    45  		}
    46  	}
    47  	return append(strs, str)
    48  }
    49  
    50  // CompareSliceStr compares two 'string' type slices.
    51  // It returns true if elements and order are both the same.
    52  func CompareSliceStr(s1, s2 []string) bool {
    53  	if len(s1) != len(s2) {
    54  		return false
    55  	}
    56  
    57  	for i := range s1 {
    58  		if s1[i] != s2[i] {
    59  			return false
    60  		}
    61  	}
    62  
    63  	return true
    64  }
    65  
    66  // CompareSliceStrU compares two 'string' type slices.
    67  // It returns true if elements are the same, and ignores the order.
    68  func CompareSliceStrU(s1, s2 []string) bool {
    69  	if len(s1) != len(s2) {
    70  		return false
    71  	}
    72  
    73  	for i := range s1 {
    74  		for j := len(s2) - 1; j >= 0; j-- {
    75  			if s1[i] == s2[j] {
    76  				s2 = append(s2[:j], s2[j+1:]...)
    77  				break
    78  			}
    79  		}
    80  	}
    81  	if len(s2) > 0 {
    82  		return false
    83  	}
    84  	return true
    85  }
    86  
    87  // IsSliceContainsStr returns true if the string exists in given slice.
    88  func IsSliceContainsStr(sl []string, str string) bool {
    89  	str = strings.ToLower(str)
    90  	for _, s := range sl {
    91  		if strings.ToLower(s) == str {
    92  			return true
    93  		}
    94  	}
    95  	return false
    96  }
    97  
    98  // IsSliceContainsInt64 returns true if the int64 exists in given slice.
    99  func IsSliceContainsInt64(sl []int64, i int64) bool {
   100  	for _, s := range sl {
   101  		if s == i {
   102  			return true
   103  		}
   104  	}
   105  	return false
   106  }
   107  
   108  // ==============================
   109  type reducetype func(interface{}) interface{}
   110  type filtertype func(interface{}) bool
   111  
   112  func InSlice(v string, sl []string) bool {
   113  	for _, vv := range sl {
   114  		if vv == v {
   115  			return true
   116  		}
   117  	}
   118  	return false
   119  }
   120  
   121  func InSet(v string, sl string, seperator ...string) bool {
   122  	var sep string
   123  	if len(seperator) > 0 {
   124  		sep = seperator[0]
   125  	}
   126  	if len(sep) == 0 {
   127  		sep = `,`
   128  	}
   129  	for _, vv := range strings.Split(sl, sep) {
   130  		if vv == v {
   131  			return true
   132  		}
   133  	}
   134  	return false
   135  }
   136  
   137  func InSliceIface(v interface{}, sl []interface{}) bool {
   138  	for _, vv := range sl {
   139  		if vv == v {
   140  			return true
   141  		}
   142  	}
   143  	return false
   144  }
   145  
   146  func InStringSlice(v string, sl []string) bool {
   147  	return InSlice(v, sl)
   148  }
   149  
   150  func InInterfaceSlice(v interface{}, sl []interface{}) bool {
   151  	return InSliceIface(v, sl)
   152  }
   153  
   154  func InIntSlice(v int, sl []int) bool {
   155  	for _, vv := range sl {
   156  		if vv == v {
   157  			return true
   158  		}
   159  	}
   160  	return false
   161  }
   162  
   163  func InInt32Slice(v int32, sl []int32) bool {
   164  	for _, vv := range sl {
   165  		if vv == v {
   166  			return true
   167  		}
   168  	}
   169  	return false
   170  }
   171  
   172  func InInt16Slice(v int16, sl []int16) bool {
   173  	for _, vv := range sl {
   174  		if vv == v {
   175  			return true
   176  		}
   177  	}
   178  	return false
   179  }
   180  
   181  func InInt64Slice(v int64, sl []int64) bool {
   182  	for _, vv := range sl {
   183  		if vv == v {
   184  			return true
   185  		}
   186  	}
   187  	return false
   188  }
   189  
   190  func InUintSlice(v uint, sl []uint) bool {
   191  	for _, vv := range sl {
   192  		if vv == v {
   193  			return true
   194  		}
   195  	}
   196  	return false
   197  }
   198  
   199  func InUint32Slice(v uint32, sl []uint32) bool {
   200  	for _, vv := range sl {
   201  		if vv == v {
   202  			return true
   203  		}
   204  	}
   205  	return false
   206  }
   207  
   208  func InUint16Slice(v uint16, sl []uint16) bool {
   209  	for _, vv := range sl {
   210  		if vv == v {
   211  			return true
   212  		}
   213  	}
   214  	return false
   215  }
   216  
   217  func InUint64Slice(v uint64, sl []uint64) bool {
   218  	for _, vv := range sl {
   219  		if vv == v {
   220  			return true
   221  		}
   222  	}
   223  	return false
   224  }
   225  
   226  func SliceRandList(min, max int) []int {
   227  	if max < min {
   228  		min, max = max, min
   229  	}
   230  	length := max - min + 1
   231  	t0 := time.Now()
   232  	rand.Seed(int64(t0.Nanosecond()))
   233  	list := rand.Perm(length)
   234  	for index := range list {
   235  		list[index] += min
   236  	}
   237  	return list
   238  }
   239  
   240  func SliceMerge(slice1, slice2 []interface{}) (c []interface{}) {
   241  	c = append(slice1, slice2...)
   242  	return
   243  }
   244  
   245  func SliceReduce(slice []interface{}, a reducetype) (dslice []interface{}) {
   246  	for _, v := range slice {
   247  		dslice = append(dslice, a(v))
   248  	}
   249  	return
   250  }
   251  
   252  func SliceRand(a []interface{}) (b interface{}) {
   253  	randnum := rand.Intn(len(a))
   254  	b = a[randnum]
   255  	return
   256  }
   257  
   258  func SliceSum(intslice []int64) (sum int64) {
   259  	for _, v := range intslice {
   260  		sum += v
   261  	}
   262  	return
   263  }
   264  
   265  func SliceFilter(slice []interface{}, a filtertype) (ftslice []interface{}) {
   266  	for _, v := range slice {
   267  		if a(v) {
   268  			ftslice = append(ftslice, v)
   269  		}
   270  	}
   271  	return
   272  }
   273  
   274  func SliceDiff(slice1, slice2 []interface{}) (diffslice []interface{}) {
   275  	for _, v := range slice1 {
   276  		if !InSliceIface(v, slice2) {
   277  			diffslice = append(diffslice, v)
   278  		}
   279  	}
   280  	return
   281  }
   282  
   283  func StringSliceDiff(slice1, slice2 []string) (diffslice []string) {
   284  	for _, v := range slice1 {
   285  		if !InSlice(v, slice2) {
   286  			diffslice = append(diffslice, v)
   287  		}
   288  	}
   289  	return
   290  }
   291  
   292  func SliceExtract(parts []string, recv ...*string) {
   293  	recvEndIndex := len(recv) - 1
   294  	if recvEndIndex < 0 {
   295  		return
   296  	}
   297  	for index, value := range parts {
   298  		if index > recvEndIndex {
   299  			break
   300  		}
   301  		*recv[index] = value
   302  	}
   303  }
   304  
   305  func UintSliceDiff(slice1, slice2 []uint) (diffslice []uint) {
   306  	for _, v := range slice1 {
   307  		if !InUintSlice(v, slice2) {
   308  			diffslice = append(diffslice, v)
   309  		}
   310  	}
   311  	return
   312  }
   313  
   314  func IntSliceDiff(slice1, slice2 []int) (diffslice []int) {
   315  	for _, v := range slice1 {
   316  		if !InIntSlice(v, slice2) {
   317  			diffslice = append(diffslice, v)
   318  		}
   319  	}
   320  	return
   321  }
   322  
   323  func Uint64SliceDiff(slice1, slice2 []uint64) (diffslice []uint64) {
   324  	for _, v := range slice1 {
   325  		if !InUint64Slice(v, slice2) {
   326  			diffslice = append(diffslice, v)
   327  		}
   328  	}
   329  	return
   330  }
   331  
   332  func Int64SliceDiff(slice1, slice2 []int64) (diffslice []int64) {
   333  	for _, v := range slice1 {
   334  		if !InInt64Slice(v, slice2) {
   335  			diffslice = append(diffslice, v)
   336  		}
   337  	}
   338  	return
   339  }
   340  
   341  func SliceIntersect(slice1, slice2 []interface{}) (diffslice []interface{}) {
   342  	for _, v := range slice1 {
   343  		if !InSliceIface(v, slice2) {
   344  			diffslice = append(diffslice, v)
   345  		}
   346  	}
   347  	return
   348  }
   349  
   350  func SliceChunk(slice []interface{}, size int) (chunkslice [][]interface{}) {
   351  	if size >= len(slice) {
   352  		chunkslice = append(chunkslice, slice)
   353  		return
   354  	}
   355  	end := size
   356  	for i := 0; i <= (len(slice) - size); i += size {
   357  		chunkslice = append(chunkslice, slice[i:end])
   358  		end += size
   359  	}
   360  	return
   361  }
   362  
   363  func SliceRange(start, end, step int64) (intslice []int64) {
   364  	for i := start; i <= end; i += step {
   365  		intslice = append(intslice, i)
   366  	}
   367  	return
   368  }
   369  
   370  func SlicePad(slice []interface{}, size int, val interface{}) []interface{} {
   371  	if size <= len(slice) {
   372  		return slice
   373  	}
   374  	for i := 0; i < (size - len(slice)); i++ {
   375  		slice = append(slice, val)
   376  	}
   377  	return slice
   378  }
   379  
   380  func SliceUnique(slice []interface{}) (uniqueslice []interface{}) {
   381  	for _, v := range slice {
   382  		if !InSliceIface(v, uniqueslice) {
   383  			uniqueslice = append(uniqueslice, v)
   384  		}
   385  	}
   386  	return
   387  }
   388  
   389  func SliceShuffle(slice []interface{}) []interface{} {
   390  	size := len(slice)
   391  	for i := 0; i < size; i++ {
   392  		a := rand.Intn(size)
   393  		b := rand.Intn(size)
   394  		if a == b {
   395  			continue
   396  		}
   397  		slice[a], slice[b] = slice[b], slice[a]
   398  	}
   399  	return slice
   400  }
   401  
   402  var ErrNotSliceType = errors.New("expects a slice type")
   403  
   404  // Shuffle 打乱数组
   405  func Shuffle(arr interface{}) error {
   406  	contentType := reflect.TypeOf(arr)
   407  	if contentType.Kind() != reflect.Slice {
   408  		return ErrNotSliceType
   409  	}
   410  	contentValue := reflect.ValueOf(arr)
   411  	source := rand.NewSource(time.Now().UnixNano())
   412  	random := rand.New(source)
   413  	len := contentValue.Len()
   414  	for i := len - 1; i > 0; i-- {
   415  		j := random.Intn(i + 1)
   416  		x, y := contentValue.Index(i).Interface(), contentValue.Index(j).Interface()
   417  		contentValue.Index(i).Set(reflect.ValueOf(y))
   418  		contentValue.Index(j).Set(reflect.ValueOf(x))
   419  	}
   420  	return nil
   421  }
   422  
   423  func SliceInsert(slice, insertion []interface{}, index int) []interface{} {
   424  	result := make([]interface{}, len(slice)+len(insertion))
   425  	at := copy(result, slice[:index])
   426  	at += copy(result[at:], insertion)
   427  	copy(result[at:], slice[index:])
   428  	return result
   429  }
   430  
   431  // SliceRemove SliceRomove(a,4,5) //a[4]
   432  func SliceRemove(slice []interface{}, start int, args ...int) []interface{} {
   433  	var end int
   434  	if len(args) == 0 {
   435  		end = start + 1
   436  	} else {
   437  		end = args[0]
   438  	}
   439  	if end > len(slice)-1 {
   440  		return slice[:start]
   441  	}
   442  	return append(slice[:start], slice[end:]...)
   443  }
   444  
   445  func SliceGet(slice []interface{}, index int, defautls ...interface{}) interface{} {
   446  	if index >= 0 && index < len(slice) {
   447  		return slice[index]
   448  	}
   449  	if len(defautls) > 0 {
   450  		if fn, ok := defautls[0].(func() interface{}); ok {
   451  			return fn()
   452  		}
   453  		return defautls[0]
   454  	}
   455  	return nil
   456  }
   457  
   458  func StrSliceGet(slice []string, index int, defautls ...string) string {
   459  	if index >= 0 && index < len(slice) {
   460  		return slice[index]
   461  	}
   462  	if len(defautls) > 0 {
   463  		return defautls[0]
   464  	}
   465  	return ``
   466  }
   467  
   468  func IntSliceGet(slice []int, index int, defautls ...int) int {
   469  	if index >= 0 && index < len(slice) {
   470  		return slice[index]
   471  	}
   472  	if len(defautls) > 0 {
   473  		return defautls[0]
   474  	}
   475  	return 0
   476  }
   477  
   478  func UintSliceGet(slice []uint, index int, defautls ...uint) uint {
   479  	if index >= 0 && index < len(slice) {
   480  		return slice[index]
   481  	}
   482  	if len(defautls) > 0 {
   483  		return defautls[0]
   484  	}
   485  	return 0
   486  }
   487  
   488  func Int32SliceGet(slice []int32, index int, defautls ...int32) int32 {
   489  	if index >= 0 && index < len(slice) {
   490  		return slice[index]
   491  	}
   492  	if len(defautls) > 0 {
   493  		return defautls[0]
   494  	}
   495  	return 0
   496  }
   497  
   498  func Uint32SliceGet(slice []uint32, index int, defautls ...uint32) uint32 {
   499  	if index >= 0 && index < len(slice) {
   500  		return slice[index]
   501  	}
   502  	if len(defautls) > 0 {
   503  		return defautls[0]
   504  	}
   505  	return 0
   506  }
   507  
   508  func Int64SliceGet(slice []int64, index int, defautls ...int64) int64 {
   509  	if index >= 0 && index < len(slice) {
   510  		return slice[index]
   511  	}
   512  	if len(defautls) > 0 {
   513  		return defautls[0]
   514  	}
   515  	return 0
   516  }
   517  
   518  func Uint64SliceGet(slice []uint64, index int, defautls ...uint64) uint64 {
   519  	if index >= 0 && index < len(slice) {
   520  		return slice[index]
   521  	}
   522  	if len(defautls) > 0 {
   523  		return defautls[0]
   524  	}
   525  	return 0
   526  }
   527  
   528  // SliceRemoveCallback : 根据条件删除
   529  // a=[]int{1,2,3,4,5,6}
   530  //
   531  //	SliceRemoveCallback(len(a), func(i int) func(bool)error{
   532  //		if a[i]!=4 {
   533  //		 	return nil
   534  //		}
   535  //		return func(inside bool)error{
   536  //			if inside {
   537  //				a=append(a[0:i],a[i+1:]...)
   538  //			}else{
   539  //				a=a[0:i]
   540  //			}
   541  //			return nil
   542  //		}
   543  //	})
   544  func SliceRemoveCallback(length int, callback func(int) func(bool) error) error {
   545  	for i, j := 0, length-1; i <= j; i++ {
   546  		if removeFunc := callback(i); removeFunc != nil {
   547  			var err error
   548  			if i+1 <= j {
   549  				err = removeFunc(true)
   550  			} else {
   551  				err = removeFunc(false)
   552  			}
   553  			if err != nil {
   554  				return err
   555  			}
   556  			i--
   557  			j--
   558  		}
   559  	}
   560  	return nil
   561  }
   562  
   563  func SplitKVRows(rows string, seperator ...string) map[string]string {
   564  	sep := `=`
   565  	if len(seperator) > 0 && len(seperator[0]) > 0 {
   566  		sep = seperator[0]
   567  	}
   568  	res := map[string]string{}
   569  	for _, row := range strings.Split(rows, StrLF) {
   570  		parts := strings.SplitN(row, sep, 2)
   571  		if len(parts) != 2 {
   572  			continue
   573  		}
   574  		parts[0] = strings.TrimSpace(parts[0])
   575  		if len(parts[0]) == 0 {
   576  			continue
   577  		}
   578  		parts[1] = strings.TrimSpace(parts[1])
   579  		res[parts[0]] = parts[1]
   580  	}
   581  	return res
   582  }
   583  
   584  func SplitKVRowsCallback(rows string, callback func(k, v string) error, seperator ...string) (err error) {
   585  	sep := `=`
   586  	if len(seperator) > 0 && len(seperator[0]) > 0 {
   587  		sep = seperator[0]
   588  	}
   589  	for _, row := range strings.Split(rows, StrLF) {
   590  		parts := strings.SplitN(row, sep, 2)
   591  		if len(parts) != 2 {
   592  			continue
   593  		}
   594  		parts[0] = strings.TrimSpace(parts[0])
   595  		if len(parts[0]) == 0 {
   596  			continue
   597  		}
   598  		parts[1] = strings.TrimSpace(parts[1])
   599  		err = callback(parts[0], parts[1])
   600  		if err != nil {
   601  			return
   602  		}
   603  	}
   604  	return
   605  }
   606  
   607  func JoinKVRows(value interface{}, seperator ...string) string {
   608  	m, y := value.(map[string]string)
   609  	if !y {
   610  		return ``
   611  	}
   612  	sep := `=`
   613  	if len(seperator) > 0 && len(seperator[0]) > 0 {
   614  		sep = seperator[0]
   615  	}
   616  	r := make([]string, 0, len(m))
   617  	for k, v := range m {
   618  		r = append(r, k+sep+v)
   619  	}
   620  	sort.Strings(r)
   621  	return strings.Join(r, "\n")
   622  }
   623  
   624  func TrimSpaceForRows(rows string) []string {
   625  	rowSlice := strings.Split(rows, StrLF)
   626  	res := make([]string, 0, len(rowSlice))
   627  	for _, row := range rowSlice {
   628  		row = strings.TrimSpace(row)
   629  		if len(row) == 0 {
   630  			continue
   631  		}
   632  		res = append(res, row)
   633  	}
   634  	return res
   635  }