添加几个php的数组函数
This commit is contained in:
parent
06e2f75000
commit
0832d679a3
|
@ -55,3 +55,15 @@ func Reduce[T, V any, K comparable](m map[K]V, fn func(K, V, T) T, r T) T {
|
|||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func Replace[K comparable, V any](m map[K]V, mm ...map[K]V) map[K]V {
|
||||
for _, n := range mm {
|
||||
for k, v := range n {
|
||||
_, ok := m[k]
|
||||
if ok {
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
|
|
@ -10,6 +10,10 @@ type IntNumber interface {
|
|||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
||||
}
|
||||
|
||||
type Number interface {
|
||||
IntNumber | ~float64 | ~float32
|
||||
}
|
||||
|
||||
func Range[T IntNumber](start, end, step T) []T {
|
||||
if step == 0 {
|
||||
panic("step can't be 0")
|
||||
|
@ -29,12 +33,13 @@ func Range[T IntNumber](start, end, step T) []T {
|
|||
return r
|
||||
}
|
||||
|
||||
// Rand 都为闭区间 [start,end]
|
||||
func Rand[T IntNumber](start, end T) T {
|
||||
end++
|
||||
return T(rand.Int63n(int64(end-start))) + start
|
||||
}
|
||||
|
||||
func Min[T IntNumber | ~float64 | ~float32](a ...T) T {
|
||||
func Min[T Number](a ...T) T {
|
||||
min := a[0]
|
||||
for _, t := range a {
|
||||
if min > t {
|
||||
|
@ -44,7 +49,7 @@ func Min[T IntNumber | ~float64 | ~float32](a ...T) T {
|
|||
return min
|
||||
}
|
||||
|
||||
func Max[T IntNumber | ~float64 | ~float32](a ...T) T {
|
||||
func Max[T Number](a ...T) T {
|
||||
max := a[0]
|
||||
for _, t := range a {
|
||||
if max < t {
|
||||
|
@ -54,7 +59,7 @@ func Max[T IntNumber | ~float64 | ~float32](a ...T) T {
|
|||
return max
|
||||
}
|
||||
|
||||
func Sum[T IntNumber | ~float64 | ~float32](a ...T) T {
|
||||
func Sum[T Number](a ...T) T {
|
||||
s := T(0)
|
||||
for _, t := range a {
|
||||
s += t
|
||||
|
@ -62,6 +67,17 @@ func Sum[T IntNumber | ~float64 | ~float32](a ...T) T {
|
|||
return s
|
||||
}
|
||||
|
||||
func ToString[T IntNumber | ~float64 | ~float32](n T) string {
|
||||
func Add[T Number](i, j T) T {
|
||||
return i + j
|
||||
}
|
||||
|
||||
func ToString[T Number](n T) string {
|
||||
return fmt.Sprintf("%v", n)
|
||||
}
|
||||
|
||||
func Abs[T Number](n T) T {
|
||||
if n >= 0 {
|
||||
return n
|
||||
}
|
||||
return -n
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package slice
|
||||
|
||||
import "github.com/fthvgb1/wp-go/helper"
|
||||
import (
|
||||
"github.com/fthvgb1/wp-go/helper"
|
||||
"github.com/fthvgb1/wp-go/helper/number"
|
||||
)
|
||||
|
||||
func Map[T, R any](arr []T, fn func(T) R) []R {
|
||||
r := make([]R, 0, len(arr))
|
||||
|
@ -190,3 +193,63 @@ func GroupBy[K comparable, T, V any](a []T, fn func(T) (K, V)) map[K][]V {
|
|||
func ToAnySlice[T any](a []T) []any {
|
||||
return Map(a, helper.ToAny[T])
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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.
|
||||
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
|
||||
}
|
||||
|
||||
func Pop[T any](a *[]T) T {
|
||||
arr := *a
|
||||
v := arr[len(arr)-1]
|
||||
|
||||
*a = append(arr[:len(arr)-1])
|
||||
return v
|
||||
}
|
||||
|
||||
func Rand[T any](a []T) (int, T) {
|
||||
i := number.Rand(0, len(a)-1)
|
||||
return i, a[i]
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -651,3 +651,192 @@ func TestWalk(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFill(t *testing.T) {
|
||||
type args[T int] struct {
|
||||
start int
|
||||
len int
|
||||
v T
|
||||
}
|
||||
type testCase[T int] struct {
|
||||
name string
|
||||
args args[T]
|
||||
want []T
|
||||
}
|
||||
tests := []testCase[int]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[int]{
|
||||
start: 2,
|
||||
len: 3,
|
||||
v: 1,
|
||||
},
|
||||
want: []int{0, 0, 1, 1, 1},
|
||||
}, {
|
||||
name: "t2",
|
||||
args: args[int]{
|
||||
start: 0,
|
||||
len: 3,
|
||||
v: 2,
|
||||
},
|
||||
want: []int{2, 2, 2},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := Fill(tt.args.start, tt.args.len, tt.args.v); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Fill() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPad(t *testing.T) {
|
||||
type args[T int] struct {
|
||||
a []T
|
||||
length int
|
||||
v T
|
||||
}
|
||||
type testCase[T int] struct {
|
||||
name string
|
||||
args args[T]
|
||||
want []T
|
||||
}
|
||||
tests := []testCase[int]{
|
||||
{
|
||||
name: "length >0",
|
||||
args: args[int]{
|
||||
a: []int{1, 2},
|
||||
length: 5,
|
||||
v: 10,
|
||||
},
|
||||
want: []int{1, 2, 10, 10, 10},
|
||||
},
|
||||
{
|
||||
name: "length <0",
|
||||
args: args[int]{
|
||||
a: []int{1, 2},
|
||||
length: -5,
|
||||
v: 10,
|
||||
},
|
||||
want: []int{10, 10, 10, 1, 2},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := Pad(tt.args.a, tt.args.length, tt.args.v); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Pad() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPop(t *testing.T) {
|
||||
type args[T int] struct {
|
||||
a *[]T
|
||||
}
|
||||
type testCase[T int] struct {
|
||||
name string
|
||||
args args[T]
|
||||
want T
|
||||
}
|
||||
a := number.Range(1, 10, 1)
|
||||
tests := []testCase[int]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[int]{
|
||||
a: &a,
|
||||
},
|
||||
want: 10,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := Pop(tt.args.a); !reflect.DeepEqual(got, tt.want) && !reflect.DeepEqual(a, number.Range(1, 9, 1)) {
|
||||
t.Errorf("Pop() = %v, want %v", got, tt.want)
|
||||
}
|
||||
fmt.Println(a)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRand(t *testing.T) {
|
||||
type args[T int] struct {
|
||||
a []T
|
||||
}
|
||||
type testCase[T int] struct {
|
||||
name string
|
||||
args args[T]
|
||||
}
|
||||
tests := []testCase[int]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[int]{
|
||||
number.Range(1, 5, 1),
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
for i := 0; i < 50; i++ {
|
||||
got, got1 := Rand(tt.args.a)
|
||||
fmt.Println(got, got1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandPop(t *testing.T) {
|
||||
type args[T int] struct {
|
||||
a *[]T
|
||||
}
|
||||
type testCase[T int] struct {
|
||||
name string
|
||||
args args[T]
|
||||
want T
|
||||
}
|
||||
a := number.Range(1, 10, 1)
|
||||
tests := []testCase[int]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[int]{
|
||||
a: &a,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
for i := 0; i < 11; i++ {
|
||||
got, l := RandPop(tt.args.a)
|
||||
fmt.Println(got, l, a)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestShift(t *testing.T) {
|
||||
type args[T int] struct {
|
||||
a *[]T
|
||||
}
|
||||
type testCase[T int] struct {
|
||||
name string
|
||||
args args[T]
|
||||
want T
|
||||
want1 int
|
||||
}
|
||||
a := number.Range(1, 10, 1)
|
||||
tests := []testCase[int]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[int]{&a},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
for i := 0; i < 11; i++ {
|
||||
got, got1 := Shift(tt.args.a)
|
||||
fmt.Println(got, got1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
35
helper/slice/slices.go
Normal file
35
helper/slice/slices.go
Normal file
|
@ -0,0 +1,35 @@
|
|||
package slice
|
||||
|
||||
func Splice[T any](a *[]T, offset, length int, replacement []T) []T {
|
||||
arr := *a
|
||||
l := len(arr)
|
||||
if length < 0 {
|
||||
panic("length must > 0")
|
||||
}
|
||||
if offset >= 0 {
|
||||
if offset+length > l {
|
||||
return nil
|
||||
} else if l > offset && l < offset+length {
|
||||
v := arr[offset:l]
|
||||
*a = append(arr[:offset], replacement...)
|
||||
return v
|
||||
} else if offset+length <= l {
|
||||
v := append([]T{}, arr[offset:offset+length]...)
|
||||
*a = append(arr[:offset], append(replacement, arr[offset+length:]...)...)
|
||||
return v
|
||||
}
|
||||
} else {
|
||||
if -offset > l {
|
||||
return nil
|
||||
} else if -offset <= l && l+offset+length < l {
|
||||
v := append([]T{}, arr[l+offset:l+offset+length]...)
|
||||
*a = append(arr[:l+offset], append(replacement, arr[l+offset+length:]...)...)
|
||||
return v
|
||||
} else if -offset <= l && l+offset+length >= l {
|
||||
v := append([]T{}, arr[l+offset:]...)
|
||||
*a = append(arr[:l+offset], replacement...)
|
||||
return v
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
79
helper/slice/slices_test.go
Normal file
79
helper/slice/slices_test.go
Normal file
|
@ -0,0 +1,79 @@
|
|||
package slice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/fthvgb1/wp-go/helper/number"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSplice(t *testing.T) {
|
||||
type args[T int] struct {
|
||||
a *[]T
|
||||
offset int
|
||||
length int
|
||||
replacement []T
|
||||
}
|
||||
type testCase[T int] struct {
|
||||
name string
|
||||
args args[T]
|
||||
want []T
|
||||
}
|
||||
a := number.Range(1, 10, 1)
|
||||
b := number.Range(1, 10, 1)
|
||||
c := number.Range(1, 10, 1)
|
||||
d := number.Range(1, 10, 1)
|
||||
tests := []testCase[int]{
|
||||
{
|
||||
name: "t1",
|
||||
args: args[int]{
|
||||
a: &a,
|
||||
offset: 3,
|
||||
length: 2,
|
||||
replacement: nil,
|
||||
},
|
||||
want: []int{4, 5},
|
||||
},
|
||||
{
|
||||
name: "t2",
|
||||
args: args[int]{
|
||||
a: &b,
|
||||
offset: 3,
|
||||
length: 2,
|
||||
replacement: []int{11, 12, 15},
|
||||
},
|
||||
want: []int{4, 5},
|
||||
},
|
||||
{
|
||||
name: "t3",
|
||||
args: args[int]{
|
||||
a: &c,
|
||||
offset: -1,
|
||||
length: 2,
|
||||
replacement: nil, //[]int{11, 12, 15},
|
||||
},
|
||||
want: []int{10},
|
||||
},
|
||||
{
|
||||
name: "t4",
|
||||
args: args[int]{
|
||||
a: &d,
|
||||
offset: -3,
|
||||
length: 5,
|
||||
replacement: []int{11, 12, 15},
|
||||
},
|
||||
want: []int{8, 9, 10},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := Splice(tt.args.a, tt.args.offset, tt.args.length, tt.args.replacement); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Splice() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
fmt.Println(a)
|
||||
fmt.Println(b)
|
||||
fmt.Println(c)
|
||||
fmt.Println(d)
|
||||
}
|
Loading…
Reference in New Issue
Block a user