wp-go/helper/slice/slice.go

307 lines
5.5 KiB
Go
Raw Normal View History

2023-01-21 11:31:23 +00:00
package slice
2023-01-13 04:31:35 +00:00
2023-01-27 15:48:48 +00:00
import (
"github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/number"
)
2023-01-23 15:42:37 +00:00
2023-01-21 11:31:23 +00:00
func Map[T, R any](arr []T, fn func(T) R) []R {
2023-01-13 04:31:35 +00:00
r := make([]R, 0, len(arr))
for _, t := range arr {
r = append(r, fn(t))
}
return r
}
2023-01-21 11:31:23 +00:00
func FilterAndMap[N any, T any](arr []T, fn func(T) (N, bool)) (r []N) {
for _, t := range arr {
x, ok := fn(t)
if ok {
r = append(r, x)
}
}
return
}
2023-01-26 16:52:59 +00:00
func Walk[T any](arr []T, fn func(*T)) {
for i := 0; i < len(arr); i++ {
fn(&arr[i])
}
}
2023-01-28 13:38:34 +00:00
func SearchFirst[T any](arr []T, fn func(T) bool) (int, T) {
2023-01-26 16:52:59 +00:00
for i, t := range arr {
if fn(t) {
return i, t
}
}
var r T
return -1, r
}
2023-01-28 13:38:34 +00:00
func SearchLast[T any](arr []T, fn func(T) bool) (int, T) {
2023-01-26 16:52:59 +00:00
for i := len(arr) - 1; i > 0; i-- {
if fn(arr[i]) {
return i, arr[i]
}
}
var r T
return -1, r
}
2023-03-04 15:57:19 +00:00
func Filter[T any](arr []T, fn func(T, int) bool) []T {
2023-01-13 04:31:35 +00:00
var r []T
2023-03-04 15:57:19 +00:00
for i, t := range arr {
if fn(t, i) {
2023-01-13 04:31:35 +00:00
r = append(r, t)
}
}
return r
}
2023-11-28 14:46:22 +00:00
func Filters[T any](arr []T, fn func(T) bool) []T {
var r []T
for _, t := range arr {
if fn(t) {
r = append(r, t)
}
}
return r
}
2023-01-13 04:31:35 +00:00
2023-01-21 11:31:23 +00:00
func Reduce[R, T any](arr []T, fn func(T, R) R, r R) R {
2023-01-13 04:31:35 +00:00
for _, t := range arr {
r = fn(t, r)
}
return r
}
func ReverseReduce[R, T any](a []T, fn func(T, R) R, r R) R {
for i := len(a) - 1; i >= 0; i-- {
r = fn(a[i], r)
}
return r
}
2023-01-21 11:31:23 +00:00
func Reverse[T any](arr []T) []T {
2023-01-13 04:31:35 +00:00
var r = make([]T, 0, len(arr))
for i := len(arr); i > 0; i-- {
r = append(r, arr[i-1])
}
return r
}
2023-01-21 11:31:23 +00:00
func ReverseSelf[T any](arr []T) []T {
2023-01-13 04:31:35 +00:00
l := len(arr)
half := l / 2
for i := 0; i < half; i++ {
arr[i], arr[l-i-1] = arr[l-i-1], arr[i]
}
return arr
}
2023-01-21 11:31:23 +00:00
func SimpleToMap[K comparable, V any](arr []V, fn func(V) K) map[K]V {
return ToMap(arr, func(v V) (K, V) {
2023-01-13 04:31:35 +00:00
return fn(v), v
}, true)
}
2023-01-21 11:31:23 +00:00
func ToMap[K comparable, V, T any](arr []V, fn func(V) (K, T), isCoverPrev bool) map[K]T {
2023-01-13 04:31:35 +00:00
m := make(map[K]T)
for _, v := range arr {
k, r := fn(v)
if !isCoverPrev {
if _, ok := m[k]; ok {
continue
}
}
m[k] = r
}
return m
}
2023-01-21 11:31:23 +00:00
func Pagination[T any](arr []T, page, pageSize int) []T {
2023-01-13 04:31:35 +00:00
start := (page - 1) * pageSize
l := len(arr)
if start > l {
start = l
}
end := start + pageSize
2023-01-13 04:31:35 +00:00
if l < end {
end = l
}
return arr[start:end]
}
func ReversePagination[T any](arr []T, page, pageSize int) []T {
end := len(arr) - (page-1)*pageSize
if end <= 0 {
return nil
}
start := end - pageSize
if start < 0 {
start = 0
}
return arr[start:end]
}
2023-01-13 04:31:35 +00:00
2023-01-21 11:31:23 +00:00
func Chunk[T any](arr []T, size int) [][]T {
2023-01-13 04:31:35 +00:00
var r [][]T
i := 0
for {
if len(arr) <= size+i {
r = append(r, arr[i:])
break
}
r = append(r, arr[i:i+size])
i += size
}
return r
}
func Slice[T any](arr []T, offset, length int) (r []T) {
l := len(arr)
if length == 0 {
length = l - offset
}
if l > offset && l >= offset+length {
2023-11-28 16:00:25 +00:00
r = arr[offset : offset+length]
2023-01-13 04:31:35 +00:00
} else if l <= offset {
return
} else if l > offset && l < offset+length {
2023-11-28 16:00:25 +00:00
r = arr[offset:]
2023-01-13 04:31:35 +00:00
}
return
}
func FilterAndToMap[K comparable, V, T any](arr []T, fn func(T, int) (K, V, bool)) map[K]V {
2023-01-21 14:56:41 +00:00
r := make(map[K]V)
for i, t := range arr {
k, v, ok := fn(t, i)
2023-01-21 14:56:41 +00:00
if ok {
r[k] = v
}
}
return r
}
2023-01-13 04:31:35 +00:00
func Comb[T any](arr []T, m int) (r [][]T) {
if m == 1 {
for _, t := range arr {
r = append(r, []T{t})
}
return
}
l := len(arr) - m
for i := 0; i <= l; i++ {
next := Slice(arr, i+1, 0)
nexRes := Comb(next, m-1)
for _, re := range nexRes {
t := append([]T{arr[i]}, re...)
r = append(r, t)
}
}
return r
}
2023-01-21 11:31:23 +00:00
2023-01-23 15:42:37 +00:00
func GroupBy[K comparable, T, V any](a []T, fn func(T) (K, V)) map[K][]V {
r := make(map[K][]V)
for _, t := range a {
k, v := fn(t)
if _, ok := r[k]; !ok {
r[k] = []V{v}
} else {
r[k] = append(r[k], v)
2023-01-21 11:31:23 +00:00
}
}
2023-01-23 15:42:37 +00:00
return r
}
func ToAnySlice[T any](a []T) []any {
return Map(a, helper.ToAny[T])
2023-01-21 11:31:23 +00:00
}
2023-01-27 15:48:48 +00:00
2023-01-28 13:38:34 +00:00
// Fill 用指定值填充一个切片
2023-01-27 15:48:48 +00:00
func Fill[T any](start, len int, v T) []T {
r := make([]T, start+len)
for i := 0; i < len; i++ {
r[start+i] = v
}
return r
}
2023-01-28 13:38:34 +00:00
// Pad 以指定长度将一个值填充进切片 returns a copy of the array padded to size specified by length with value. If length is positive then the array is padded on the right, if it's negative then on the left. If the absolute value of length is less than or equal to the length of the array then no padding takes place.
2023-01-27 15:48:48 +00:00
func Pad[T any](a []T, length int, v T) []T {
l := len(a)
if length > l {
return append(a, Fill(0, length-l, v)...)
} else if length < 0 && -length > l-1 {
return append(Fill(0, -length-2, v), a...)
}
return a
}
2023-01-28 13:38:34 +00:00
// Pop 弹出最后一个元素
2023-01-27 15:48:48 +00:00
func Pop[T any](a *[]T) T {
arr := *a
v := arr[len(arr)-1]
*a = append(arr[:len(arr)-1])
return v
}
2023-01-28 13:38:34 +00:00
// Rand 随机取一个元素
2023-01-27 15:48:48 +00:00
func Rand[T any](a []T) (int, T) {
2023-01-31 06:25:25 +00:00
var r T
if len(a) < 1 {
return -1, r
} else if len(a) == 1 {
return 0, a[0]
}
2023-01-27 15:48:48 +00:00
i := number.Rand(0, len(a)-1)
return i, a[i]
}
2023-01-28 13:38:34 +00:00
// RandPop 随机弹出一个元素并返回那个剩余长度
2023-01-27 15:48:48 +00:00
func RandPop[T any](a *[]T) (T, int) {
arr := *a
if len(arr) == 0 {
var r T
return r, 0
}
i := number.Rand(0, len(arr)-1)
v := arr[i]
if len(arr)-1 == i {
*a = append(arr[:i])
} else {
*a = append(arr[:i], arr[i+1:]...)
}
return v, len(arr) - 1
}
2023-01-28 13:38:34 +00:00
// Shift 将切片的第一个单元移出并作为结果返回
2023-01-27 15:48:48 +00:00
func Shift[T any](a *[]T) (T, int) {
arr := *a
l := len(arr)
if l > 0 {
v := arr[0]
*a = arr[1:]
return v, l - 1
}
var r T
return r, 0
}
2023-03-04 15:57:19 +00:00
func IndexOf[T comparable](a []T, v T) int {
for i, t := range a {
if t == v {
return i
}
}
return -1
}
func ForEach[T any](a []T, fn func(i int, v T)) {
for i, t := range a {
fn(i, t)
}
}