You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

slice.go 2.4KB

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