code.gitea.io/gitea@v1.19.3/modules/util/slice.go (about)

     1  // Copyright 2022 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  // Most of the functions in this file can have better implementations with "golang.org/x/exp/slices".
     5  // However, "golang.org/x/exp" is experimental and unreliable, we shouldn't use it.
     6  // So lets waiting for the "slices" has be promoted to the main repository one day.
     7  
     8  package util
     9  
    10  import "strings"
    11  
    12  // SliceContains returns true if the target exists in the slice.
    13  func SliceContains[T comparable](slice []T, target T) bool {
    14  	return SliceContainsFunc(slice, func(t T) bool { return t == target })
    15  }
    16  
    17  // SliceContainsFunc returns true if any element in the slice satisfies the targetFunc.
    18  func SliceContainsFunc[T any](slice []T, targetFunc func(T) bool) bool {
    19  	for _, v := range slice {
    20  		if targetFunc(v) {
    21  			return true
    22  		}
    23  	}
    24  	return false
    25  }
    26  
    27  // SliceContainsString sequential searches if string exists in slice.
    28  func SliceContainsString(slice []string, target string, insensitive ...bool) bool {
    29  	if len(insensitive) != 0 && insensitive[0] {
    30  		target = strings.ToLower(target)
    31  		return SliceContainsFunc(slice, func(t string) bool { return strings.ToLower(t) == target })
    32  	}
    33  
    34  	return SliceContains(slice, target)
    35  }
    36  
    37  // SliceSortedEqual returns true if the two slices will be equal when they get sorted.
    38  // It doesn't require that the slices have been sorted, and it doesn't sort them either.
    39  func SliceSortedEqual[T comparable](s1, s2 []T) bool {
    40  	if len(s1) != len(s2) {
    41  		return false
    42  	}
    43  
    44  	counts := make(map[T]int, len(s1))
    45  	for _, v := range s1 {
    46  		counts[v]++
    47  	}
    48  	for _, v := range s2 {
    49  		counts[v]--
    50  	}
    51  
    52  	for _, v := range counts {
    53  		if v != 0 {
    54  			return false
    55  		}
    56  	}
    57  	return true
    58  }
    59  
    60  // SliceEqual returns true if the two slices are equal.
    61  func SliceEqual[T comparable](s1, s2 []T) bool {
    62  	if len(s1) != len(s2) {
    63  		return false
    64  	}
    65  
    66  	for i, v := range s1 {
    67  		if s2[i] != v {
    68  			return false
    69  		}
    70  	}
    71  	return true
    72  }
    73  
    74  // SliceRemoveAll removes all the target elements from the slice.
    75  func SliceRemoveAll[T comparable](slice []T, target T) []T {
    76  	return SliceRemoveAllFunc(slice, func(t T) bool { return t == target })
    77  }
    78  
    79  // SliceRemoveAllFunc removes all elements which satisfy the targetFunc from the slice.
    80  func SliceRemoveAllFunc[T comparable](slice []T, targetFunc func(T) bool) []T {
    81  	idx := 0
    82  	for _, v := range slice {
    83  		if targetFunc(v) {
    84  			continue
    85  		}
    86  		slice[idx] = v
    87  		idx++
    88  	}
    89  	return slice[:idx]
    90  }