aboutsummaryrefslogtreecommitdiffstats
path: root/library/go/slices
diff options
context:
space:
mode:
authorqrort <qrort@yandex-team.com>2022-11-30 23:47:12 +0300
committerqrort <qrort@yandex-team.com>2022-11-30 23:47:12 +0300
commit22f8ae0e3f5d68b92aecccdf96c1d841a0334311 (patch)
treebffa27765faf54126ad44bcafa89fadecb7a73d7 /library/go/slices
parent332b99e2173f0425444abb759eebcb2fafaa9209 (diff)
downloadydb-22f8ae0e3f5d68b92aecccdf96c1d841a0334311.tar.gz
validate canons without yatest_common
Diffstat (limited to 'library/go/slices')
-rw-r--r--library/go/slices/contains.go90
-rw-r--r--library/go/slices/contains_all.go23
-rw-r--r--library/go/slices/contains_any.go72
-rw-r--r--library/go/slices/dedup.go109
-rw-r--r--library/go/slices/equal.go22
-rw-r--r--library/go/slices/filter.go29
-rw-r--r--library/go/slices/group_by.go90
-rw-r--r--library/go/slices/intersects.go83
-rw-r--r--library/go/slices/join.go14
-rw-r--r--library/go/slices/map.go27
-rw-r--r--library/go/slices/reverse.go83
-rw-r--r--library/go/slices/shuffle.go95
12 files changed, 737 insertions, 0 deletions
diff --git a/library/go/slices/contains.go b/library/go/slices/contains.go
new file mode 100644
index 0000000000..0b68109f5c
--- /dev/null
+++ b/library/go/slices/contains.go
@@ -0,0 +1,90 @@
+package slices
+
+import (
+ "bytes"
+ "net"
+
+ "github.com/gofrs/uuid"
+ "golang.org/x/exp/slices"
+)
+
+// ContainsString checks if string slice contains given string.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsString = slices.Contains[string]
+
+// ContainsBool checks if bool slice contains given bool.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsBool = slices.Contains[bool]
+
+// ContainsInt checks if int slice contains given int
+var ContainsInt = slices.Contains[int]
+
+// ContainsInt8 checks if int8 slice contains given int8.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsInt8 = slices.Contains[int8]
+
+// ContainsInt16 checks if int16 slice contains given int16.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsInt16 = slices.Contains[int16]
+
+// ContainsInt32 checks if int32 slice contains given int32.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsInt32 = slices.Contains[int32]
+
+// ContainsInt64 checks if int64 slice contains given int64.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsInt64 = slices.Contains[int64]
+
+// ContainsUint checks if uint slice contains given uint.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsUint = slices.Contains[uint]
+
+// ContainsUint8 checks if uint8 slice contains given uint8.
+func ContainsUint8(haystack []uint8, needle uint8) bool {
+ return bytes.IndexByte(haystack, needle) != -1
+}
+
+// ContainsUint16 checks if uint16 slice contains given uint16.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsUint16 = slices.Contains[uint16]
+
+// ContainsUint32 checks if uint32 slice contains given uint32.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsUint32 = slices.Contains[uint32]
+
+// ContainsUint64 checks if uint64 slice contains given uint64.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsUint64 = slices.Contains[uint64]
+
+// ContainsFloat32 checks if float32 slice contains given float32.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsFloat32 = slices.Contains[float32]
+
+// ContainsFloat64 checks if float64 slice contains given float64.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsFloat64 = slices.Contains[float64]
+
+// ContainsByte checks if byte slice contains given byte
+func ContainsByte(haystack []byte, needle byte) bool {
+ return bytes.IndexByte(haystack, needle) != -1
+}
+
+// ContainsIP checks if net.IP slice contains given net.IP
+func ContainsIP(haystack []net.IP, needle net.IP) bool {
+ for _, e := range haystack {
+ if e.Equal(needle) {
+ return true
+ }
+ }
+ return false
+}
+
+// ContainsUUID checks if UUID slice contains given UUID.
+// Deprecated: use golang.org/x/exp/slices.Contains instead
+var ContainsUUID = slices.Contains[uuid.UUID]
+
+// Contains checks if slice of T contains given T
+// Deprecated: use golang.org/x/exp/slices.Contains instead.
+func Contains[E comparable](haystack []E, needle E) (bool, error) {
+ return slices.Contains(haystack, needle), nil
+}
diff --git a/library/go/slices/contains_all.go b/library/go/slices/contains_all.go
new file mode 100644
index 0000000000..3c3e8e1878
--- /dev/null
+++ b/library/go/slices/contains_all.go
@@ -0,0 +1,23 @@
+package slices
+
+// ContainsAll checks if slice of type E contains all elements of given slice, order independent
+func ContainsAll[E comparable](haystack []E, needle []E) bool {
+ m := make(map[E]struct{}, len(haystack))
+ for _, i := range haystack {
+ m[i] = struct{}{}
+ }
+ for _, v := range needle {
+ if _, ok := m[v]; !ok {
+ return false
+ }
+ }
+ return true
+}
+
+// ContainsAllStrings checks if string slice contains all elements of given slice
+// Deprecated: use ContainsAll instead
+var ContainsAllStrings = ContainsAll[string]
+
+// ContainsAllBools checks if bool slice contains all elements of given slice
+// Deprecated: use ContainsAll instead
+var ContainsAllBools = ContainsAll[bool]
diff --git a/library/go/slices/contains_any.go b/library/go/slices/contains_any.go
new file mode 100644
index 0000000000..0fc6a7ace4
--- /dev/null
+++ b/library/go/slices/contains_any.go
@@ -0,0 +1,72 @@
+package slices
+
+import (
+ "bytes"
+)
+
+// ContainsAny checks if slice of type E contains any element from given slice
+func ContainsAny[E comparable](haystack, needle []E) bool {
+ return len(Intersection(haystack, needle)) > 0
+}
+
+// ContainsAnyString checks if string slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyString = ContainsAny[string]
+
+// ContainsAnyBool checks if bool slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyBool = ContainsAny[bool]
+
+// ContainsAnyInt checks if int slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyInt = ContainsAny[int]
+
+// ContainsAnyInt8 checks if int8 slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyInt8 = ContainsAny[int8]
+
+// ContainsAnyInt16 checks if int16 slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyInt16 = ContainsAny[int16]
+
+// ContainsAnyInt32 checks if int32 slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyInt32 = ContainsAny[int32]
+
+// ContainsAnyInt64 checks if int64 slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyInt64 = ContainsAny[int64]
+
+// ContainsAnyUint checks if uint slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyUint = ContainsAny[uint]
+
+// ContainsAnyUint8 checks if uint8 slice contains any element from given slice
+func ContainsAnyUint8(haystack []uint8, needle []uint8) bool {
+ return bytes.Contains(haystack, needle)
+}
+
+// ContainsAnyUint16 checks if uint16 slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyUint16 = ContainsAny[uint16]
+
+// ContainsAnyUint32 checks if uint32 slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyUint32 = ContainsAny[uint32]
+
+// ContainsAnyUint64 checks if uint64 slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyUint64 = ContainsAny[uint64]
+
+// ContainsAnyFloat32 checks if float32 slice contains any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyFloat32 = ContainsAny[float32]
+
+// ContainsAnyFloat64 checks if float64 slice any element from given slice
+// Deprecated: use ContainsAny instead.
+var ContainsAnyFloat64 = ContainsAny[float64]
+
+// ContainsAnyByte checks if byte slice contains any element from given slice
+func ContainsAnyByte(haystack []byte, needle []byte) bool {
+ return bytes.Contains(haystack, needle)
+}
diff --git a/library/go/slices/dedup.go b/library/go/slices/dedup.go
new file mode 100644
index 0000000000..365f3b2d74
--- /dev/null
+++ b/library/go/slices/dedup.go
@@ -0,0 +1,109 @@
+package slices
+
+import (
+ "sort"
+
+ "golang.org/x/exp/constraints"
+ "golang.org/x/exp/slices"
+)
+
+// Dedup removes duplicate values from slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+func Dedup[E constraints.Ordered](s []E) []E {
+ if len(s) < 2 {
+ return s
+ }
+ slices.Sort(s)
+ tmp := s[:1]
+ cur := s[0]
+ for i := 1; i < len(s); i++ {
+ if s[i] != cur {
+ tmp = append(tmp, s[i])
+ cur = s[i]
+ }
+ }
+ return tmp
+}
+
+// DedupBools removes duplicate values from bool slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+func DedupBools(a []bool) []bool {
+ if len(a) < 2 {
+ return a
+ }
+ sort.Slice(a, func(i, j int) bool { return a[i] != a[j] })
+ tmp := a[:1]
+ cur := a[0]
+ for i := 1; i < len(a); i++ {
+ if a[i] != cur {
+ tmp = append(tmp, a[i])
+ cur = a[i]
+ }
+ }
+ return tmp
+}
+
+// DedupStrings removes duplicate values from string slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupStrings = Dedup[string]
+
+// DedupInts removes duplicate values from ints slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupInts = Dedup[int]
+
+// DedupInt8s removes duplicate values from int8 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupInt8s = Dedup[int8]
+
+// DedupInt16s removes duplicate values from int16 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupInt16s = Dedup[int16]
+
+// DedupInt32s removes duplicate values from int32 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupInt32s = Dedup[int32]
+
+// DedupInt64s removes duplicate values from int64 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupInt64s = Dedup[int64]
+
+// DedupUints removes duplicate values from uint slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupUints = Dedup[uint]
+
+// DedupUint8s removes duplicate values from uint8 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupUint8s = Dedup[uint8]
+
+// DedupUint16s removes duplicate values from uint16 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupUint16s = Dedup[uint16]
+
+// DedupUint32s removes duplicate values from uint32 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupUint32s = Dedup[uint32]
+
+// DedupUint64s removes duplicate values from uint64 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupUint64s = Dedup[uint64]
+
+// DedupFloat32s removes duplicate values from float32 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupFloat32s = Dedup[float32]
+
+// DedupFloat64s removes duplicate values from float64 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Dedup instead.
+var DedupFloat64s = Dedup[float64]
diff --git a/library/go/slices/equal.go b/library/go/slices/equal.go
new file mode 100644
index 0000000000..3c698c7865
--- /dev/null
+++ b/library/go/slices/equal.go
@@ -0,0 +1,22 @@
+package slices
+
+// EqualUnordered checks if slices of type E are equal, order independent.
+func EqualUnordered[E comparable](a []E, b []E) bool {
+ if len(a) != len(b) {
+ return false
+ }
+
+ ma := make(map[E]struct{})
+ for _, v := range a {
+ ma[v] = struct{}{}
+ }
+ l := len(ma)
+ for _, v := range b {
+ ma[v] = struct{}{}
+ }
+ return len(ma) == l
+}
+
+// EqualAnyOrderStrings checks if string slices are equal, order independent.
+// Deprecated: use EqualUnordered instead.
+var EqualAnyOrderStrings = EqualUnordered[string]
diff --git a/library/go/slices/filter.go b/library/go/slices/filter.go
new file mode 100644
index 0000000000..8b383bfcb2
--- /dev/null
+++ b/library/go/slices/filter.go
@@ -0,0 +1,29 @@
+package slices
+
+import (
+ "golang.org/x/exp/slices"
+)
+
+// Filter reduces slice values using given function.
+// It operates with a copy of given slice
+func Filter[S ~[]T, T any](s S, fn func(T) bool) S {
+ if len(s) == 0 {
+ return s
+ }
+ return Reduce(slices.Clone(s), fn)
+}
+
+// Reduce is like Filter, but modifies original slice.
+func Reduce[S ~[]T, T any](s S, fn func(T) bool) S {
+ if len(s) == 0 {
+ return s
+ }
+ var p int
+ for _, v := range s {
+ if fn(v) {
+ s[p] = v
+ p++
+ }
+ }
+ return s[:p]
+}
diff --git a/library/go/slices/group_by.go b/library/go/slices/group_by.go
new file mode 100644
index 0000000000..fb61a29314
--- /dev/null
+++ b/library/go/slices/group_by.go
@@ -0,0 +1,90 @@
+package slices
+
+import (
+ "fmt"
+)
+
+func createNotUniqueKeyError[T comparable](key T) error {
+ return fmt.Errorf("duplicated key \"%v\" found. keys are supposed to be unique", key)
+}
+
+// GroupBy groups slice entities into map by key provided via keyGetter.
+func GroupBy[S ~[]T, T any, K comparable](s S, keyGetter func(T) K) map[K][]T {
+ res := map[K][]T{}
+
+ for _, entity := range s {
+ key := keyGetter(entity)
+ res[key] = append(res[key], entity)
+ }
+
+ return res
+}
+
+// GroupByUniqueKey groups slice entities into map by key provided via keyGetter with assumption that each key is unique.
+//
+// Returns an error in case of key ununiqueness.
+func GroupByUniqueKey[S ~[]T, T any, K comparable](s S, keyGetter func(T) K) (map[K]T, error) {
+ res := map[K]T{}
+
+ for _, entity := range s {
+ key := keyGetter(entity)
+
+ _, duplicated := res[key]
+ if duplicated {
+ return res, createNotUniqueKeyError(key)
+ }
+
+ res[key] = entity
+ }
+
+ return res, nil
+}
+
+// IndexedEntity stores an entity of original slice with its initial index in that slice
+type IndexedEntity[T any] struct {
+ Value T
+ Index int
+}
+
+// GroupByWithIndex groups slice entities into map by key provided via keyGetter.
+// Each entity of underlying result slice contains the value itself and its index in the original slice
+// (See IndexedEntity).
+func GroupByWithIndex[S ~[]T, T any, K comparable](s S, keyGetter func(T) K) map[K][]IndexedEntity[T] {
+ res := map[K][]IndexedEntity[T]{}
+
+ for i, entity := range s {
+ key := keyGetter(entity)
+ res[key] = append(res[key], IndexedEntity[T]{
+ Value: entity,
+ Index: i,
+ })
+ }
+
+ return res
+}
+
+// GroupByUniqueKeyWithIndex groups slice entities into map by key provided via keyGetter with assumption that
+// each key is unique.
+// Each result entity contains the value itself and its index in the original slice
+// (See IndexedEntity).
+//
+// Returns an error in case of key ununiqueness.
+func GroupByUniqueKeyWithIndex[S ~[]T, T any, K comparable](s S, keyGetter func(T) K) (map[K]IndexedEntity[T], error) {
+ res := map[K]IndexedEntity[T]{}
+
+ for i, entity := range s {
+ key := keyGetter(entity)
+
+ _, duplicated := res[key]
+ if duplicated {
+ return res, createNotUniqueKeyError(key)
+ }
+
+ res[key] = IndexedEntity[T]{
+ Value: entity,
+ Index: i,
+ }
+ }
+
+ return res, nil
+}
diff --git a/library/go/slices/intersects.go b/library/go/slices/intersects.go
new file mode 100644
index 0000000000..b7785952df
--- /dev/null
+++ b/library/go/slices/intersects.go
@@ -0,0 +1,83 @@
+package slices
+
+// Intersection returns intersection for slices of various built-in types
+func Intersection[E comparable](a, b []E) []E {
+ if len(a) == 0 || len(b) == 0 {
+ return nil
+ }
+
+ p, s := a, b
+ if len(b) > len(a) {
+ p, s = b, a
+ }
+
+ m := make(map[E]struct{})
+ for _, i := range p {
+ m[i] = struct{}{}
+ }
+
+ var res []E
+ for _, v := range s {
+ if _, exists := m[v]; exists {
+ res = append(res, v)
+ }
+ }
+
+ return res
+}
+
+// IntersectStrings returns intersection of two string slices
+// Deprecated: use Intersection instead.
+var IntersectStrings = Intersection[string]
+
+// IntersectInts returns intersection of two int slices
+// Deprecated: use Intersection instead.
+var IntersectInts = Intersection[int]
+
+// IntersectInt8s returns intersection of two int8 slices
+// Deprecated: use Intersection instead.
+var IntersectInt8s = Intersection[int8]
+
+// IntersectInt16s returns intersection of two int16 slices
+// Deprecated: use Intersection instead.
+var IntersectInt16s = Intersection[int16]
+
+// IntersectInt32s returns intersection of two int32 slices
+// Deprecated: use Intersection instead.
+var IntersectInt32s = Intersection[int32]
+
+// IntersectInt64s returns intersection of two int64 slices
+// Deprecated: use Intersection instead.
+var IntersectInt64s = Intersection[int64]
+
+// IntersectUints returns intersection of two uint slices
+// Deprecated: use Intersection instead.
+var IntersectUints = Intersection[uint]
+
+// IntersectUint8s returns intersection of two uint8 slices
+// Deprecated: use Intersection instead.
+var IntersectUint8s = Intersection[uint8]
+
+// IntersectUint16s returns intersection of two uint16 slices
+// Deprecated: use Intersection instead.
+var IntersectUint16s = Intersection[uint16]
+
+// IntersectUint32s returns intersection of two uint32 slices
+// Deprecated: use Intersection instead.
+var IntersectUint32s = Intersection[uint32]
+
+// IntersectUint64s returns intersection of two uint64 slices
+// Deprecated: use Intersection instead.
+var IntersectUint64s = Intersection[uint64]
+
+// IntersectFloat32s returns intersection of two float32 slices
+// Deprecated: use Intersection instead.
+var IntersectFloat32s = Intersection[float32]
+
+// IntersectFloat64s returns intersection of two float64 slices
+// Deprecated: use Intersection instead.
+var IntersectFloat64s = Intersection[float64]
+
+// IntersectBools returns intersection of two bool slices
+// Deprecated: use Intersection instead.
+var IntersectBools = Intersection[bool]
diff --git a/library/go/slices/join.go b/library/go/slices/join.go
new file mode 100644
index 0000000000..7b72db5ed1
--- /dev/null
+++ b/library/go/slices/join.go
@@ -0,0 +1,14 @@
+package slices
+
+import (
+ "fmt"
+ "strings"
+)
+
+// Join joins slice of any types
+func Join(s interface{}, glue string) string {
+ if t, ok := s.([]string); ok {
+ return strings.Join(t, glue)
+ }
+ return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(s)), glue), "[]")
+}
diff --git a/library/go/slices/map.go b/library/go/slices/map.go
new file mode 100644
index 0000000000..943261f786
--- /dev/null
+++ b/library/go/slices/map.go
@@ -0,0 +1,27 @@
+package slices
+
+// Map applies given function to every value of slice
+func Map[S ~[]T, T, M any](s S, fn func(T) M) []M {
+ if s == nil {
+ return []M(nil)
+ }
+ if len(s) == 0 {
+ return make([]M, 0)
+ }
+ res := make([]M, len(s))
+ for i, v := range s {
+ res[i] = fn(v)
+ }
+ return res
+}
+
+// Mutate is like Map, but it prohibits type changes and modifies original slice.
+func Mutate[S ~[]T, T any](s S, fn func(T) T) S {
+ if len(s) == 0 {
+ return s
+ }
+ for i, v := range s {
+ s[i] = fn(v)
+ }
+ return s
+}
diff --git a/library/go/slices/reverse.go b/library/go/slices/reverse.go
new file mode 100644
index 0000000000..a436617b67
--- /dev/null
+++ b/library/go/slices/reverse.go
@@ -0,0 +1,83 @@
+package slices
+
+// Reverse reverses given slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+func Reverse[E any](s []E) []E {
+ if len(s) < 2 {
+ return s
+ }
+ for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
+ s[i], s[j] = s[j], s[i]
+ }
+ return s
+}
+
+// ReverseStrings reverses given string slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseStrings = Reverse[string]
+
+// ReverseInts reverses given int slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseInts = Reverse[int]
+
+// ReverseInt8s reverses given int8 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseInt8s = Reverse[int8]
+
+// ReverseInt16s reverses given int16 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseInt16s = Reverse[int16]
+
+// ReverseInt32s reverses given int32 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseInt32s = Reverse[int32]
+
+// ReverseInt64s reverses given int64 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseInt64s = Reverse[int64]
+
+// ReverseUints reverses given uint slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseUints = Reverse[uint]
+
+// ReverseUint8s reverses given uint8 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseUint8s = Reverse[uint8]
+
+// ReverseUint16s reverses given uint16 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseUint16s = Reverse[uint16]
+
+// ReverseUint32s reverses given uint32 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseUint32s = Reverse[uint32]
+
+// ReverseUint64s reverses given uint64 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseUint64s = Reverse[uint64]
+
+// ReverseFloat32s reverses given float32 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseFloat32s = Reverse[float32]
+
+// ReverseFloat64s reverses given float64 slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseFloat64s = Reverse[float64]
+
+// ReverseBools reverses given bool slice.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Reverse instead.
+var ReverseBools = Reverse[bool]
diff --git a/library/go/slices/shuffle.go b/library/go/slices/shuffle.go
new file mode 100644
index 0000000000..5df9b33c3c
--- /dev/null
+++ b/library/go/slices/shuffle.go
@@ -0,0 +1,95 @@
+package slices
+
+import (
+ "math/rand"
+)
+
+// Shuffle shuffles values in slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+func Shuffle[E any](a []E, src rand.Source) []E {
+ if len(a) < 2 {
+ return a
+ }
+ shuffle(src)(len(a), func(i, j int) {
+ a[i], a[j] = a[j], a[i]
+ })
+ return a
+}
+
+// ShuffleStrings shuffles values in string slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleStrings = Shuffle[string]
+
+// ShuffleInts shuffles values in int slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleInts = Shuffle[int]
+
+// ShuffleInt8s shuffles values in int8 slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleInt8s = Shuffle[int8]
+
+// ShuffleInt16s shuffles values in int16 slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleInt16s = Shuffle[int16]
+
+// ShuffleInt32s shuffles values in int32 slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleInt32s = Shuffle[int32]
+
+// ShuffleInt64s shuffles values in int64 slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleInt64s = Shuffle[int64]
+
+// ShuffleUints shuffles values in uint slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleUints = Shuffle[uint]
+
+// ShuffleUint8s shuffles values in uint8 slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleUint8s = Shuffle[uint8]
+
+// ShuffleUint16s shuffles values in uint16 slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleUint16s = Shuffle[uint16]
+
+// ShuffleUint32s shuffles values in uint32 slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleUint32s = Shuffle[uint32]
+
+// ShuffleUint64s shuffles values in uint64 slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleUint64s = Shuffle[uint64]
+
+// ShuffleFloat32s shuffles values in float32 slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleFloat32s = Shuffle[float32]
+
+// ShuffleFloat64s shuffles values in float64 slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleFloat64s = Shuffle[float64]
+
+// ShuffleBools shuffles values in bool slice using given or pseudo-random source.
+// It will alter original non-empty slice, consider copy it beforehand.
+// Deprecated: use Shuffle instead.
+var ShuffleBools = Shuffle[bool]
+
+func shuffle(src rand.Source) func(n int, swap func(i, j int)) {
+ shuf := rand.Shuffle
+ if src != nil {
+ shuf = rand.New(src).Shuffle
+ }
+ return shuf
+}