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

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