...

Source file src/github.com/go-task/slim-sprig/v3/list.go

Documentation: github.com/go-task/slim-sprig/v3

     1  package sprig
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"reflect"
     7  	"sort"
     8  )
     9  
    10  // Reflection is used in these functions so that slices and arrays of strings,
    11  // ints, and other types not implementing []interface{} can be worked with.
    12  // For example, this is useful if you need to work on the output of regexs.
    13  
    14  func list(v ...interface{}) []interface{} {
    15  	return v
    16  }
    17  
    18  func push(list interface{}, v interface{}) []interface{} {
    19  	l, err := mustPush(list, v)
    20  	if err != nil {
    21  		panic(err)
    22  	}
    23  
    24  	return l
    25  }
    26  
    27  func mustPush(list interface{}, v interface{}) ([]interface{}, error) {
    28  	tp := reflect.TypeOf(list).Kind()
    29  	switch tp {
    30  	case reflect.Slice, reflect.Array:
    31  		l2 := reflect.ValueOf(list)
    32  
    33  		l := l2.Len()
    34  		nl := make([]interface{}, l)
    35  		for i := 0; i < l; i++ {
    36  			nl[i] = l2.Index(i).Interface()
    37  		}
    38  
    39  		return append(nl, v), nil
    40  
    41  	default:
    42  		return nil, fmt.Errorf("Cannot push on type %s", tp)
    43  	}
    44  }
    45  
    46  func prepend(list interface{}, v interface{}) []interface{} {
    47  	l, err := mustPrepend(list, v)
    48  	if err != nil {
    49  		panic(err)
    50  	}
    51  
    52  	return l
    53  }
    54  
    55  func mustPrepend(list interface{}, v interface{}) ([]interface{}, error) {
    56  	//return append([]interface{}{v}, list...)
    57  
    58  	tp := reflect.TypeOf(list).Kind()
    59  	switch tp {
    60  	case reflect.Slice, reflect.Array:
    61  		l2 := reflect.ValueOf(list)
    62  
    63  		l := l2.Len()
    64  		nl := make([]interface{}, l)
    65  		for i := 0; i < l; i++ {
    66  			nl[i] = l2.Index(i).Interface()
    67  		}
    68  
    69  		return append([]interface{}{v}, nl...), nil
    70  
    71  	default:
    72  		return nil, fmt.Errorf("Cannot prepend on type %s", tp)
    73  	}
    74  }
    75  
    76  func chunk(size int, list interface{}) [][]interface{} {
    77  	l, err := mustChunk(size, list)
    78  	if err != nil {
    79  		panic(err)
    80  	}
    81  
    82  	return l
    83  }
    84  
    85  func mustChunk(size int, list interface{}) ([][]interface{}, error) {
    86  	tp := reflect.TypeOf(list).Kind()
    87  	switch tp {
    88  	case reflect.Slice, reflect.Array:
    89  		l2 := reflect.ValueOf(list)
    90  
    91  		l := l2.Len()
    92  
    93  		cs := int(math.Floor(float64(l-1)/float64(size)) + 1)
    94  		nl := make([][]interface{}, cs)
    95  
    96  		for i := 0; i < cs; i++ {
    97  			clen := size
    98  			if i == cs-1 {
    99  				clen = int(math.Floor(math.Mod(float64(l), float64(size))))
   100  				if clen == 0 {
   101  					clen = size
   102  				}
   103  			}
   104  
   105  			nl[i] = make([]interface{}, clen)
   106  
   107  			for j := 0; j < clen; j++ {
   108  				ix := i*size + j
   109  				nl[i][j] = l2.Index(ix).Interface()
   110  			}
   111  		}
   112  
   113  		return nl, nil
   114  
   115  	default:
   116  		return nil, fmt.Errorf("Cannot chunk type %s", tp)
   117  	}
   118  }
   119  
   120  func last(list interface{}) interface{} {
   121  	l, err := mustLast(list)
   122  	if err != nil {
   123  		panic(err)
   124  	}
   125  
   126  	return l
   127  }
   128  
   129  func mustLast(list interface{}) (interface{}, error) {
   130  	tp := reflect.TypeOf(list).Kind()
   131  	switch tp {
   132  	case reflect.Slice, reflect.Array:
   133  		l2 := reflect.ValueOf(list)
   134  
   135  		l := l2.Len()
   136  		if l == 0 {
   137  			return nil, nil
   138  		}
   139  
   140  		return l2.Index(l - 1).Interface(), nil
   141  	default:
   142  		return nil, fmt.Errorf("Cannot find last on type %s", tp)
   143  	}
   144  }
   145  
   146  func first(list interface{}) interface{} {
   147  	l, err := mustFirst(list)
   148  	if err != nil {
   149  		panic(err)
   150  	}
   151  
   152  	return l
   153  }
   154  
   155  func mustFirst(list interface{}) (interface{}, error) {
   156  	tp := reflect.TypeOf(list).Kind()
   157  	switch tp {
   158  	case reflect.Slice, reflect.Array:
   159  		l2 := reflect.ValueOf(list)
   160  
   161  		l := l2.Len()
   162  		if l == 0 {
   163  			return nil, nil
   164  		}
   165  
   166  		return l2.Index(0).Interface(), nil
   167  	default:
   168  		return nil, fmt.Errorf("Cannot find first on type %s", tp)
   169  	}
   170  }
   171  
   172  func rest(list interface{}) []interface{} {
   173  	l, err := mustRest(list)
   174  	if err != nil {
   175  		panic(err)
   176  	}
   177  
   178  	return l
   179  }
   180  
   181  func mustRest(list interface{}) ([]interface{}, error) {
   182  	tp := reflect.TypeOf(list).Kind()
   183  	switch tp {
   184  	case reflect.Slice, reflect.Array:
   185  		l2 := reflect.ValueOf(list)
   186  
   187  		l := l2.Len()
   188  		if l == 0 {
   189  			return nil, nil
   190  		}
   191  
   192  		nl := make([]interface{}, l-1)
   193  		for i := 1; i < l; i++ {
   194  			nl[i-1] = l2.Index(i).Interface()
   195  		}
   196  
   197  		return nl, nil
   198  	default:
   199  		return nil, fmt.Errorf("Cannot find rest on type %s", tp)
   200  	}
   201  }
   202  
   203  func initial(list interface{}) []interface{} {
   204  	l, err := mustInitial(list)
   205  	if err != nil {
   206  		panic(err)
   207  	}
   208  
   209  	return l
   210  }
   211  
   212  func mustInitial(list interface{}) ([]interface{}, error) {
   213  	tp := reflect.TypeOf(list).Kind()
   214  	switch tp {
   215  	case reflect.Slice, reflect.Array:
   216  		l2 := reflect.ValueOf(list)
   217  
   218  		l := l2.Len()
   219  		if l == 0 {
   220  			return nil, nil
   221  		}
   222  
   223  		nl := make([]interface{}, l-1)
   224  		for i := 0; i < l-1; i++ {
   225  			nl[i] = l2.Index(i).Interface()
   226  		}
   227  
   228  		return nl, nil
   229  	default:
   230  		return nil, fmt.Errorf("Cannot find initial on type %s", tp)
   231  	}
   232  }
   233  
   234  func sortAlpha(list interface{}) []string {
   235  	k := reflect.Indirect(reflect.ValueOf(list)).Kind()
   236  	switch k {
   237  	case reflect.Slice, reflect.Array:
   238  		a := strslice(list)
   239  		s := sort.StringSlice(a)
   240  		s.Sort()
   241  		return s
   242  	}
   243  	return []string{strval(list)}
   244  }
   245  
   246  func reverse(v interface{}) []interface{} {
   247  	l, err := mustReverse(v)
   248  	if err != nil {
   249  		panic(err)
   250  	}
   251  
   252  	return l
   253  }
   254  
   255  func mustReverse(v interface{}) ([]interface{}, error) {
   256  	tp := reflect.TypeOf(v).Kind()
   257  	switch tp {
   258  	case reflect.Slice, reflect.Array:
   259  		l2 := reflect.ValueOf(v)
   260  
   261  		l := l2.Len()
   262  		// We do not sort in place because the incoming array should not be altered.
   263  		nl := make([]interface{}, l)
   264  		for i := 0; i < l; i++ {
   265  			nl[l-i-1] = l2.Index(i).Interface()
   266  		}
   267  
   268  		return nl, nil
   269  	default:
   270  		return nil, fmt.Errorf("Cannot find reverse on type %s", tp)
   271  	}
   272  }
   273  
   274  func compact(list interface{}) []interface{} {
   275  	l, err := mustCompact(list)
   276  	if err != nil {
   277  		panic(err)
   278  	}
   279  
   280  	return l
   281  }
   282  
   283  func mustCompact(list interface{}) ([]interface{}, error) {
   284  	tp := reflect.TypeOf(list).Kind()
   285  	switch tp {
   286  	case reflect.Slice, reflect.Array:
   287  		l2 := reflect.ValueOf(list)
   288  
   289  		l := l2.Len()
   290  		nl := []interface{}{}
   291  		var item interface{}
   292  		for i := 0; i < l; i++ {
   293  			item = l2.Index(i).Interface()
   294  			if !empty(item) {
   295  				nl = append(nl, item)
   296  			}
   297  		}
   298  
   299  		return nl, nil
   300  	default:
   301  		return nil, fmt.Errorf("Cannot compact on type %s", tp)
   302  	}
   303  }
   304  
   305  func uniq(list interface{}) []interface{} {
   306  	l, err := mustUniq(list)
   307  	if err != nil {
   308  		panic(err)
   309  	}
   310  
   311  	return l
   312  }
   313  
   314  func mustUniq(list interface{}) ([]interface{}, error) {
   315  	tp := reflect.TypeOf(list).Kind()
   316  	switch tp {
   317  	case reflect.Slice, reflect.Array:
   318  		l2 := reflect.ValueOf(list)
   319  
   320  		l := l2.Len()
   321  		dest := []interface{}{}
   322  		var item interface{}
   323  		for i := 0; i < l; i++ {
   324  			item = l2.Index(i).Interface()
   325  			if !inList(dest, item) {
   326  				dest = append(dest, item)
   327  			}
   328  		}
   329  
   330  		return dest, nil
   331  	default:
   332  		return nil, fmt.Errorf("Cannot find uniq on type %s", tp)
   333  	}
   334  }
   335  
   336  func inList(haystack []interface{}, needle interface{}) bool {
   337  	for _, h := range haystack {
   338  		if reflect.DeepEqual(needle, h) {
   339  			return true
   340  		}
   341  	}
   342  	return false
   343  }
   344  
   345  func without(list interface{}, omit ...interface{}) []interface{} {
   346  	l, err := mustWithout(list, omit...)
   347  	if err != nil {
   348  		panic(err)
   349  	}
   350  
   351  	return l
   352  }
   353  
   354  func mustWithout(list interface{}, omit ...interface{}) ([]interface{}, error) {
   355  	tp := reflect.TypeOf(list).Kind()
   356  	switch tp {
   357  	case reflect.Slice, reflect.Array:
   358  		l2 := reflect.ValueOf(list)
   359  
   360  		l := l2.Len()
   361  		res := []interface{}{}
   362  		var item interface{}
   363  		for i := 0; i < l; i++ {
   364  			item = l2.Index(i).Interface()
   365  			if !inList(omit, item) {
   366  				res = append(res, item)
   367  			}
   368  		}
   369  
   370  		return res, nil
   371  	default:
   372  		return nil, fmt.Errorf("Cannot find without on type %s", tp)
   373  	}
   374  }
   375  
   376  func has(needle interface{}, haystack interface{}) bool {
   377  	l, err := mustHas(needle, haystack)
   378  	if err != nil {
   379  		panic(err)
   380  	}
   381  
   382  	return l
   383  }
   384  
   385  func mustHas(needle interface{}, haystack interface{}) (bool, error) {
   386  	if haystack == nil {
   387  		return false, nil
   388  	}
   389  	tp := reflect.TypeOf(haystack).Kind()
   390  	switch tp {
   391  	case reflect.Slice, reflect.Array:
   392  		l2 := reflect.ValueOf(haystack)
   393  		var item interface{}
   394  		l := l2.Len()
   395  		for i := 0; i < l; i++ {
   396  			item = l2.Index(i).Interface()
   397  			if reflect.DeepEqual(needle, item) {
   398  				return true, nil
   399  			}
   400  		}
   401  
   402  		return false, nil
   403  	default:
   404  		return false, fmt.Errorf("Cannot find has on type %s", tp)
   405  	}
   406  }
   407  
   408  // $list := [1, 2, 3, 4, 5]
   409  // slice $list     -> list[0:5] = list[:]
   410  // slice $list 0 3 -> list[0:3] = list[:3]
   411  // slice $list 3 5 -> list[3:5]
   412  // slice $list 3   -> list[3:5] = list[3:]
   413  func slice(list interface{}, indices ...interface{}) interface{} {
   414  	l, err := mustSlice(list, indices...)
   415  	if err != nil {
   416  		panic(err)
   417  	}
   418  
   419  	return l
   420  }
   421  
   422  func mustSlice(list interface{}, indices ...interface{}) (interface{}, error) {
   423  	tp := reflect.TypeOf(list).Kind()
   424  	switch tp {
   425  	case reflect.Slice, reflect.Array:
   426  		l2 := reflect.ValueOf(list)
   427  
   428  		l := l2.Len()
   429  		if l == 0 {
   430  			return nil, nil
   431  		}
   432  
   433  		var start, end int
   434  		if len(indices) > 0 {
   435  			start = toInt(indices[0])
   436  		}
   437  		if len(indices) < 2 {
   438  			end = l
   439  		} else {
   440  			end = toInt(indices[1])
   441  		}
   442  
   443  		return l2.Slice(start, end).Interface(), nil
   444  	default:
   445  		return nil, fmt.Errorf("list should be type of slice or array but %s", tp)
   446  	}
   447  }
   448  
   449  func concat(lists ...interface{}) interface{} {
   450  	var res []interface{}
   451  	for _, list := range lists {
   452  		tp := reflect.TypeOf(list).Kind()
   453  		switch tp {
   454  		case reflect.Slice, reflect.Array:
   455  			l2 := reflect.ValueOf(list)
   456  			for i := 0; i < l2.Len(); i++ {
   457  				res = append(res, l2.Index(i).Interface())
   458  			}
   459  		default:
   460  			panic(fmt.Sprintf("Cannot concat type %s as list", tp))
   461  		}
   462  	}
   463  	return res
   464  }
   465  

View as plain text