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

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