github.com/andeya/ameda@v1.5.3/interfaces.go (about)

     1  package ameda
     2  
     3  // OneInterface try to return the first element, otherwise return zero value.
     4  func OneInterface(i []interface{}) interface{} {
     5  	if len(i) > 0 {
     6  		return i[0]
     7  	}
     8  	return nil
     9  }
    10  
    11  // InterfacesCopy creates a copy of the interface slice.
    12  func InterfacesCopy(i []interface{}) []interface{} {
    13  	b := make([]interface{}, len(i))
    14  	copy(b, i)
    15  	return b
    16  }
    17  
    18  // InterfacesToStrings converts interface slice to string slice.
    19  func InterfacesToStrings(i []interface{}) []string {
    20  	r := make([]string, len(i))
    21  	for k, v := range i {
    22  		r[k] = InterfaceToString(v)
    23  	}
    24  	return r
    25  }
    26  
    27  // InterfacesToBools converts interface slice to bool slice.
    28  // NOTE:
    29  //
    30  //	0 is false, other numbers are true
    31  func InterfacesToBools(i []interface{}) ([]bool, error) {
    32  	var err error
    33  	r := make([]bool, len(i))
    34  	for k, v := range i {
    35  		r[k], err = InterfaceToBool(v)
    36  		if err != nil {
    37  			return r, err
    38  		}
    39  	}
    40  	return r, nil
    41  }
    42  
    43  // InterfacesToFloat32s converts interface slice to float32 slice.
    44  func InterfacesToFloat32s(i []interface{}) ([]float32, error) {
    45  	var err error
    46  	r := make([]float32, len(i))
    47  	for k, v := range i {
    48  		r[k], err = InterfaceToFloat32(v)
    49  		if err != nil {
    50  			return r, err
    51  		}
    52  	}
    53  	return r, nil
    54  }
    55  
    56  // InterfacesToFloat64s converts interface slice to float64 slice.
    57  func InterfacesToFloat64s(i []interface{}) ([]float64, error) {
    58  	var err error
    59  	r := make([]float64, len(i))
    60  	for k, v := range i {
    61  		r[k], err = InterfaceToFloat64(v)
    62  		if err != nil {
    63  			return r, err
    64  		}
    65  	}
    66  	return r, nil
    67  }
    68  
    69  // InterfacesToInts converts interface slice to int slice.
    70  func InterfacesToInts(i []interface{}) ([]int, error) {
    71  	var err error
    72  	r := make([]int, len(i))
    73  	for k, v := range i {
    74  		r[k], err = InterfaceToInt(v)
    75  		if err != nil {
    76  			return r, err
    77  		}
    78  	}
    79  	return r, nil
    80  }
    81  
    82  // InterfacesToInt8s converts interface slice to int8 slice.
    83  func InterfacesToInt8s(i []interface{}) ([]int8, error) {
    84  	var err error
    85  	r := make([]int8, len(i))
    86  	for k, v := range i {
    87  		r[k], err = InterfaceToInt8(v)
    88  		if err != nil {
    89  			return r, err
    90  		}
    91  	}
    92  	return r, nil
    93  }
    94  
    95  // InterfacesToInt16s converts interface slice to int16 slice.
    96  func InterfacesToInt16s(i []interface{}) ([]int16, error) {
    97  	var err error
    98  	r := make([]int16, len(i))
    99  	for k, v := range i {
   100  		r[k], err = InterfaceToInt16(v)
   101  		if err != nil {
   102  			return r, err
   103  		}
   104  	}
   105  	return r, nil
   106  }
   107  
   108  // InterfacesToInt32s converts interface slice to int32 slice.
   109  func InterfacesToInt32s(i []interface{}) ([]int32, error) {
   110  	var err error
   111  	r := make([]int32, len(i))
   112  	for k, v := range i {
   113  		r[k], err = InterfaceToInt32(v)
   114  		if err != nil {
   115  			return r, err
   116  		}
   117  	}
   118  	return r, nil
   119  }
   120  
   121  // InterfacesToInt64s converts interface slice to int64 slice.
   122  func InterfacesToInt64s(i []interface{}) ([]int64, error) {
   123  	var err error
   124  	r := make([]int64, len(i))
   125  	for k, v := range i {
   126  		r[k], err = InterfaceToInt64(v)
   127  		if err != nil {
   128  			return r, err
   129  		}
   130  	}
   131  	return r, nil
   132  }
   133  
   134  // InterfacesToUints converts interface slice to uint slice.
   135  func InterfacesToUints(i []interface{}) ([]uint, error) {
   136  	var err error
   137  	r := make([]uint, len(i))
   138  	for k, v := range i {
   139  		r[k], err = InterfaceToUint(v)
   140  		if err != nil {
   141  			return r, err
   142  		}
   143  	}
   144  	return r, nil
   145  }
   146  
   147  // InterfacesToUint8s converts interface slice to uint8 slice.
   148  func InterfacesToUint8s(i []interface{}) ([]uint8, error) {
   149  	var err error
   150  	r := make([]uint8, len(i))
   151  	for k, v := range i {
   152  		r[k], err = InterfaceToUint8(v)
   153  		if err != nil {
   154  			return r, err
   155  		}
   156  	}
   157  	return r, nil
   158  }
   159  
   160  // InterfacesToUint16s converts interface slice to uint16 slice.
   161  func InterfacesToUint16s(i []interface{}) ([]uint16, error) {
   162  	var err error
   163  	r := make([]uint16, len(i))
   164  	for k, v := range i {
   165  		r[k], err = InterfaceToUint16(v)
   166  		if err != nil {
   167  			return r, err
   168  		}
   169  	}
   170  	return r, nil
   171  }
   172  
   173  // InterfacesToUint32s converts interface slice to uint32 slice.
   174  func InterfacesToUint32s(i []interface{}) ([]uint32, error) {
   175  	var err error
   176  	r := make([]uint32, len(i))
   177  	for k, v := range i {
   178  		r[k], err = InterfaceToUint32(v)
   179  		if err != nil {
   180  			return r, err
   181  		}
   182  	}
   183  	return r, nil
   184  }
   185  
   186  // InterfacesToUint64s converts interface slice to uint64 slice.
   187  func InterfacesToUint64s(i []interface{}) ([]uint64, error) {
   188  	var err error
   189  	r := make([]uint64, len(i))
   190  	for k, v := range i {
   191  		r[k], err = InterfaceToUint64(v)
   192  		if err != nil {
   193  			return r, err
   194  		}
   195  	}
   196  	return r, nil
   197  }
   198  
   199  // InterfacesCopyWithin copies part of an slice to another location in the current slice.
   200  // @target
   201  //
   202  //	Zero-based index at which to copy the sequence to. If negative, target will be counted from the end.
   203  //
   204  // @start
   205  //
   206  //	Zero-based index at which to start copying elements from. If negative, start will be counted from the end.
   207  //
   208  // @end
   209  //
   210  //	Zero-based index at which to end copying elements from. CopyWithin copies up to but not including end.
   211  //	If negative, end will be counted from the end.
   212  //	If end is omitted, CopyWithin will copy until the last index (default to len(s)).
   213  func InterfacesCopyWithin(i []interface{}, target, start int, end ...int) {
   214  	target = fixIndex(len(i), target, true)
   215  	if target == len(i) {
   216  		return
   217  	}
   218  	sub := InterfacesSlice(i, start, end...)
   219  	for k, v := range sub {
   220  		i[target+k] = v
   221  	}
   222  }
   223  
   224  // InterfacesEvery tests whether all elements in the slice pass the test implemented by the provided function.
   225  // NOTE:
   226  //
   227  //	Calling this method on an empty slice will return true for any condition!
   228  func InterfacesEvery(i []interface{}, fn func(i []interface{}, k int, v interface{}) bool) bool {
   229  	for k, v := range i {
   230  		if !fn(i, k, v) {
   231  			return false
   232  		}
   233  	}
   234  	return true
   235  }
   236  
   237  // InterfacesFill changes all elements in the current slice to a value, from a start index to an end index.
   238  // @value
   239  //
   240  //	Zero-based index at which to copy the sequence to. If negative, target will be counted from the end.
   241  //
   242  // @start
   243  //
   244  //	Zero-based index at which to start copying elements from. If negative, start will be counted from the end.
   245  //
   246  // @end
   247  //
   248  //	Zero-based index at which to end copying elements from. CopyWithin copies up to but not including end.
   249  //	If negative, end will be counted from the end.
   250  //	If end is omitted, CopyWithin will copy until the last index (default to len(s)).
   251  func InterfacesFill(i []interface{}, value []interface{}, start int, end ...int) {
   252  	fixedStart, fixedEnd, ok := fixRange(len(i), start, end...)
   253  	if !ok {
   254  		return
   255  	}
   256  	for k := fixedStart; k < fixedEnd; k++ {
   257  		i[k] = value
   258  	}
   259  }
   260  
   261  // InterfacesFilter creates a new slice with all elements that pass the test implemented by the provided function.
   262  func InterfacesFilter(i []interface{}, fn func(i []interface{}, k int, v interface{}) bool) []interface{} {
   263  	ret := make([]interface{}, 0)
   264  	for k, v := range i {
   265  		if fn(i, k, v) {
   266  			ret = append(ret, v)
   267  		}
   268  	}
   269  	return ret
   270  }
   271  
   272  // InterfacesFind returns the key-value of the first element in the provided slice that satisfies the provided testing function.
   273  // NOTE:
   274  //
   275  //	If not found, k = -1
   276  func InterfacesFind(i []interface{}, fn func(i []interface{}, k int, v interface{}) bool) (k int, v interface{}) {
   277  	for k, v := range i {
   278  		if fn(i, k, v) {
   279  			return k, v
   280  		}
   281  	}
   282  	return -1, 0
   283  }
   284  
   285  // InterfacesIncludes determines whether an slice includes a certain value among its entries.
   286  // @fromIndex
   287  //
   288  //	The index to start the search at. Defaults to 0.
   289  func InterfacesIncludes(i []interface{}, valueToFind int64, fromIndex ...int) bool {
   290  	return InterfacesIndexOf(i, valueToFind, fromIndex...) > -1
   291  }
   292  
   293  // InterfacesIndexOf returns the first index at which a given element can be found in the slice, or -1 if it is not present.
   294  // @fromIndex
   295  //
   296  //	The index to start the search at. Defaults to 0.
   297  func InterfacesIndexOf(i []interface{}, searchElement int64, fromIndex ...int) int {
   298  	idx := getFromIndex(len(i), fromIndex...)
   299  	for k, v := range i[idx:] {
   300  		if searchElement == v {
   301  			return k + idx
   302  		}
   303  	}
   304  	return -1
   305  }
   306  
   307  // InterfacesLastIndexOf returns the last index at which a given element can be found in the slice, or -1 if it is not present.
   308  // @fromIndex
   309  //
   310  //	The index to start the search at. Defaults to 0.
   311  func InterfacesLastIndexOf(i []interface{}, searchElement int64, fromIndex ...int) int {
   312  	idx := getFromIndex(len(i), fromIndex...)
   313  	for k := len(i) - 1; k >= idx; k-- {
   314  		if searchElement == i[k] {
   315  			return k
   316  		}
   317  	}
   318  	return -1
   319  }
   320  
   321  // InterfacesMap creates a new slice populated with the results of calling a provided function
   322  // on every element in the calling slice.
   323  func InterfacesMap(i []interface{}, fn func(i []interface{}, k int, v interface{}) int64) []int64 {
   324  	ret := make([]int64, len(i))
   325  	for k, v := range i {
   326  		ret[k] = fn(i, k, v)
   327  	}
   328  	return ret
   329  }
   330  
   331  // InterfacesPop removes the last element from an slice and returns that element.
   332  // This method changes the length of the slice.
   333  func InterfacesPop(i *[]interface{}) (interface{}, bool) {
   334  	a := *i
   335  	if len(a) == 0 {
   336  		return 0, false
   337  	}
   338  	lastIndex := len(a) - 1
   339  	last := a[lastIndex]
   340  	a = a[:lastIndex]
   341  	*i = a[:len(a):len(a)]
   342  	return last, true
   343  }
   344  
   345  // InterfacesPush adds one or more elements to the end of an slice and returns the new length of the slice.
   346  func InterfacesPush(i *[]interface{}, element ...interface{}) int {
   347  	*i = append(*i, element...)
   348  	return len(*i)
   349  }
   350  
   351  // InterfacesPushDistinct adds one or more new elements that do not exist in the current slice at the end.
   352  func InterfacesPushDistinct(i []interface{}, element ...interface{}) []interface{} {
   353  L:
   354  	for _, v := range element {
   355  		for _, vv := range i {
   356  			if vv == v {
   357  				continue L
   358  			}
   359  		}
   360  		i = append(i, v)
   361  	}
   362  	return i
   363  }
   364  
   365  // InterfacesReduce executes a reducer function (that you provide) on each element of the slice,
   366  // resulting in a single output value.
   367  // @accumulator
   368  //
   369  //	The accumulator accumulates callback's return values.
   370  //	It is the accumulated value previously returned in the last invocation of the callback—or initialValue,
   371  //	if it was supplied (see below).
   372  //
   373  // @initialValue
   374  //
   375  //	A value to use as the first argument to the first call of the callback.
   376  //	If no initialValue is supplied, the first element in the slice will be used and skipped.
   377  func InterfacesReduce(
   378  	i []interface{},
   379  	fn func(i []interface{}, k int, v, accumulator interface{}) interface{}, initialValue ...interface{},
   380  ) interface{} {
   381  	if len(i) == 0 {
   382  		return 0
   383  	}
   384  	start := 0
   385  	acc := i[start]
   386  	if len(initialValue) > 0 {
   387  		acc = initialValue[0]
   388  	} else {
   389  		start += 1
   390  	}
   391  	for k := start; k < len(i); k++ {
   392  		acc = fn(i, k, i[k], acc)
   393  	}
   394  	return acc
   395  }
   396  
   397  // InterfacesReduceRight applies a function against an accumulator and each value of the slice (from right-to-left)
   398  // to reduce it to a single value.
   399  // @accumulator
   400  //
   401  //	The accumulator accumulates callback's return values.
   402  //	It is the accumulated value previously returned in the last invocation of the callback—or initialValue,
   403  //	if it was supplied (see below).
   404  //
   405  // @initialValue
   406  //
   407  //	A value to use as the first argument to the first call of the callback.
   408  //	If no initialValue is supplied, the first element in the slice will be used and skipped.
   409  func InterfacesReduceRight(
   410  	i []interface{},
   411  	fn func(i []interface{}, k int, v, accumulator interface{}) interface{}, initialValue ...interface{},
   412  ) interface{} {
   413  	if len(i) == 0 {
   414  		return 0
   415  	}
   416  	end := len(i) - 1
   417  	acc := i[end]
   418  	if len(initialValue) > 0 {
   419  		acc = initialValue[0]
   420  	} else {
   421  		end -= 1
   422  	}
   423  	for k := end; k >= 0; k-- {
   424  		acc = fn(i, k, i[k], acc)
   425  	}
   426  	return acc
   427  }
   428  
   429  // InterfacesReverse reverses an slice in place.
   430  func InterfacesReverse(i []interface{}) {
   431  	first := 0
   432  	last := len(i) - 1
   433  	for first < last {
   434  		i[first], i[last] = i[last], i[first]
   435  		first++
   436  		last--
   437  	}
   438  }
   439  
   440  // InterfacesShift removes the first element from an slice and returns that removed element.
   441  // This method changes the length of the slice.
   442  func InterfacesShift(i *[]interface{}) (interface{}, bool) {
   443  	a := *i
   444  	if len(a) == 0 {
   445  		return 0, false
   446  	}
   447  	first := a[0]
   448  	a = a[1:]
   449  	*i = a[:len(a):len(a)]
   450  	return first, true
   451  }
   452  
   453  // InterfacesSlice returns a copy of a portion of an slice into a new slice object selected
   454  // from begin to end (end not included) where begin and end represent the index of items in that slice.
   455  // The original slice will not be modified.
   456  func InterfacesSlice(i []interface{}, begin int, end ...int) []interface{} {
   457  	fixedStart, fixedEnd, ok := fixRange(len(i), begin, end...)
   458  	if !ok {
   459  		return []interface{}{}
   460  	}
   461  	return InterfacesCopy(i[fixedStart:fixedEnd])
   462  }
   463  
   464  // InterfacesSome tests whether at least one element in the slice passes the test implemented by the provided function.
   465  // NOTE:
   466  //
   467  //	Calling this method on an empty slice returns false for any condition!
   468  func InterfacesSome(i []interface{}, fn func(i []interface{}, k int, v interface{}) bool) bool {
   469  	for k, v := range i {
   470  		if fn(i, k, v) {
   471  			return true
   472  		}
   473  	}
   474  	return false
   475  }
   476  
   477  // InterfacesSplice changes the contents of an slice by removing or replacing
   478  // existing elements and/or adding new elements in place.
   479  func InterfacesSplice(i *[]interface{}, start, deleteCount int, items ...interface{}) {
   480  	a := *i
   481  	if deleteCount < 0 {
   482  		deleteCount = 0
   483  	}
   484  	start, end, _ := fixRange(len(a), start, start+1+deleteCount)
   485  	deleteCount = end - start - 1
   486  	for k := 0; k < len(items); k++ {
   487  		if deleteCount > 0 {
   488  			// replace
   489  			a[start] = items[k]
   490  			deleteCount--
   491  			start++
   492  		} else {
   493  			// insert
   494  			lastSlice := InterfacesCopy(a[start:])
   495  			items = items[k:]
   496  			a = append(a[:start], items...)
   497  			a = append(a[:start+len(items)], lastSlice...)
   498  			*i = a[:len(a):len(a)]
   499  			return
   500  		}
   501  	}
   502  	if deleteCount > 0 {
   503  		a = append(a[:start], a[start+1+deleteCount:]...)
   504  	}
   505  	*i = a[:len(a):len(a)]
   506  }
   507  
   508  // InterfacesUnshift adds one or more elements to the beginning of an slice and returns the new length of the slice.
   509  func InterfacesUnshift(i *[]interface{}, element ...interface{}) int {
   510  	*i = append(element, *i...)
   511  	return len(*i)
   512  }
   513  
   514  // InterfacesUnshiftDistinct adds one or more new elements that do not exist in the current slice to the beginning
   515  // and returns the new length of the slice.
   516  func InterfacesUnshiftDistinct(i *[]interface{}, element ...interface{}) int {
   517  	a := *i
   518  	if len(element) == 0 {
   519  		return len(a)
   520  	}
   521  	m := make(map[interface{}]bool, len(element))
   522  	r := make([]interface{}, 0, len(a)+len(element))
   523  L:
   524  	for _, v := range element {
   525  		if m[v] {
   526  			continue
   527  		}
   528  		m[v] = true
   529  		for _, vv := range a {
   530  			if vv == v {
   531  				continue L
   532  			}
   533  		}
   534  		r = append(r, v)
   535  	}
   536  	r = append(r, a...)
   537  	*i = r[:len(r):len(r)]
   538  	return len(r)
   539  }
   540  
   541  // InterfacesRemoveFirst removes the first matched elements from the slice,
   542  // and returns the new length of the slice.
   543  func InterfacesRemoveFirst(p *[]interface{}, elements ...interface{}) int {
   544  	a := *p
   545  	m := make(map[interface{}]struct{}, len(elements))
   546  	for _, element := range elements {
   547  		if _, ok := m[element]; ok {
   548  			continue
   549  		}
   550  		m[element] = struct{}{}
   551  		for k, v := range a {
   552  			if v == element {
   553  				a = append(a[:k], a[k+1:]...)
   554  				break
   555  			}
   556  		}
   557  	}
   558  	n := len(a)
   559  	*p = a[:n:n]
   560  	return n
   561  }
   562  
   563  // InterfacesRemoveEvery removes all the elements from the slice,
   564  // and returns the new length of the slice.
   565  func InterfacesRemoveEvery(p *[]interface{}, elements ...interface{}) int {
   566  	a := *p
   567  	m := make(map[interface{}]struct{}, len(elements))
   568  	for _, element := range elements {
   569  		if _, ok := m[element]; ok {
   570  			continue
   571  		}
   572  		m[element] = struct{}{}
   573  		for i := 0; i < len(a); i++ {
   574  			if a[i] == element {
   575  				a = append(a[:i], a[i+1:]...)
   576  				i--
   577  			}
   578  		}
   579  	}
   580  	n := len(a)
   581  	*p = a[:n:n]
   582  	return n
   583  }
   584  
   585  // InterfacesConcat is used to merge two or more slices.
   586  // This method does not change the existing slices, but instead returns a new slice.
   587  func InterfacesConcat(i ...[]interface{}) []interface{} {
   588  	var totalLen int
   589  	for _, v := range i {
   590  		totalLen += len(v)
   591  	}
   592  	ret := make([]interface{}, totalLen)
   593  	dst := ret
   594  	for _, v := range i {
   595  		n := copy(dst, v)
   596  		dst = dst[n:]
   597  	}
   598  	return ret
   599  }
   600  
   601  // InterfacesIntersect calculates intersection of two or more slices,
   602  // and returns the count of each element.
   603  func InterfacesIntersect(i ...[]interface{}) (intersectCount map[interface{}]int) {
   604  	if len(i) == 0 {
   605  		return nil
   606  	}
   607  	for _, v := range i {
   608  		if len(v) == 0 {
   609  			return nil
   610  		}
   611  	}
   612  	counts := make([]map[interface{}]int, len(i))
   613  	for k, v := range i {
   614  		counts[k] = interfacesDistinct(v, nil)
   615  	}
   616  	intersectCount = counts[0]
   617  L:
   618  	for k, v := range intersectCount {
   619  		for _, c := range counts[1:] {
   620  			v2 := c[k]
   621  			if v2 == 0 {
   622  				delete(intersectCount, k)
   623  				continue L
   624  			}
   625  			if v > v2 {
   626  				v = v2
   627  			}
   628  		}
   629  		intersectCount[k] = v
   630  	}
   631  	return intersectCount
   632  }
   633  
   634  // InterfacesDistinct calculates the count of each different element,
   635  // and only saves these different elements in place if changeSlice is true.
   636  func InterfacesDistinct(i *[]interface{}, changeSlice bool) (distinctCount map[interface{}]int) {
   637  	if !changeSlice {
   638  		return interfacesDistinct(*i, nil)
   639  	}
   640  	a := (*i)[:0]
   641  	distinctCount = interfacesDistinct(*i, &a)
   642  	n := len(distinctCount)
   643  	*i = a[:n:n]
   644  	return distinctCount
   645  }
   646  
   647  func interfacesDistinct(src []interface{}, dst *[]interface{}) map[interface{}]int {
   648  	m := make(map[interface{}]int, len(src))
   649  	if dst == nil {
   650  		for _, v := range src {
   651  			n := m[v]
   652  			m[v] = n + 1
   653  		}
   654  	} else {
   655  		a := *dst
   656  		for _, v := range src {
   657  			n := m[v]
   658  			m[v] = n + 1
   659  			if n == 0 {
   660  				a = append(a, v)
   661  			}
   662  		}
   663  		*dst = a
   664  	}
   665  	return m
   666  }