commit
8d8ab4ab9b
|
@ -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
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -3,13 +3,23 @@ package number
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _ = func() any {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
return nil
|
||||||
|
}()
|
||||||
|
|
||||||
type IntNumber interface {
|
type IntNumber interface {
|
||||||
~int | ~int64 | ~int32 | ~int8 | ~int16 |
|
~int | ~int64 | ~int32 | ~int8 | ~int16 |
|
||||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Number interface {
|
||||||
|
IntNumber | ~float64 | ~float32
|
||||||
|
}
|
||||||
|
|
||||||
func Range[T IntNumber](start, end, step T) []T {
|
func Range[T IntNumber](start, end, step T) []T {
|
||||||
if step == 0 {
|
if step == 0 {
|
||||||
panic("step can't be 0")
|
panic("step can't be 0")
|
||||||
|
@ -29,12 +39,13 @@ func Range[T IntNumber](start, end, step T) []T {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rand 都为闭区间 [start,end]
|
||||||
func Rand[T IntNumber](start, end T) T {
|
func Rand[T IntNumber](start, end T) T {
|
||||||
end++
|
end++
|
||||||
return T(rand.Int63n(int64(end-start))) + start
|
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]
|
min := a[0]
|
||||||
for _, t := range a {
|
for _, t := range a {
|
||||||
if min > t {
|
if min > t {
|
||||||
|
@ -44,7 +55,7 @@ func Min[T IntNumber | ~float64 | ~float32](a ...T) T {
|
||||||
return min
|
return min
|
||||||
}
|
}
|
||||||
|
|
||||||
func Max[T IntNumber | ~float64 | ~float32](a ...T) T {
|
func Max[T Number](a ...T) T {
|
||||||
max := a[0]
|
max := a[0]
|
||||||
for _, t := range a {
|
for _, t := range a {
|
||||||
if max < t {
|
if max < t {
|
||||||
|
@ -54,7 +65,7 @@ func Max[T IntNumber | ~float64 | ~float32](a ...T) T {
|
||||||
return max
|
return max
|
||||||
}
|
}
|
||||||
|
|
||||||
func Sum[T IntNumber | ~float64 | ~float32](a ...T) T {
|
func Sum[T Number](a ...T) T {
|
||||||
s := T(0)
|
s := T(0)
|
||||||
for _, t := range a {
|
for _, t := range a {
|
||||||
s += t
|
s += t
|
||||||
|
@ -62,6 +73,28 @@ func Sum[T IntNumber | ~float64 | ~float32](a ...T) T {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToString[T IntNumber | ~float64 | ~float32](n T) string {
|
func Add[T Number](i, j T) T {
|
||||||
|
return i + j
|
||||||
|
}
|
||||||
|
func Sub[T Number](i, j T) T {
|
||||||
|
return i - j
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToString[T Number](n T) string {
|
||||||
return fmt.Sprintf("%v", n)
|
return fmt.Sprintf("%v", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Abs[T Number](n T) T {
|
||||||
|
if n >= 0 {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
return -n
|
||||||
|
}
|
||||||
|
|
||||||
|
func Mul[T Number](i, j T) T {
|
||||||
|
return i * j
|
||||||
|
}
|
||||||
|
|
||||||
|
func Divide[T Number](i, j T) T {
|
||||||
|
return i / j
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package number
|
package number
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -187,6 +188,32 @@ func TestRand(t *testing.T) {
|
||||||
if got > tt.args.end || got < tt.args.start {
|
if got > tt.args.end || got < tt.args.start {
|
||||||
t.Errorf("RandNum() = %v, range error", got)
|
t.Errorf("RandNum() = %v, range error", got)
|
||||||
}
|
}
|
||||||
|
fmt.Println(got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAbs(t *testing.T) {
|
||||||
|
type args[T Number] struct {
|
||||||
|
n T
|
||||||
|
}
|
||||||
|
type testCase[T Number] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
want T
|
||||||
|
}
|
||||||
|
tests := []testCase[int]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[int]{-1},
|
||||||
|
want: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := Abs(tt.args.n); got != tt.want {
|
||||||
|
t.Errorf("Abs() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package slice
|
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 {
|
func Map[T, R any](arr []T, fn func(T) R) []R {
|
||||||
r := make([]R, 0, len(arr))
|
r := make([]R, 0, len(arr))
|
||||||
|
@ -20,6 +23,32 @@ func FilterAndMap[N any, T any](arr []T, fn func(T) (N, bool)) (r []N) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Walk[T any](arr []T, fn func(*T)) {
|
||||||
|
for i := 0; i < len(arr); i++ {
|
||||||
|
fn(&arr[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SearchFirst[T any](arr []T, fn func(T) bool) (int, T) {
|
||||||
|
for i, t := range arr {
|
||||||
|
if fn(t) {
|
||||||
|
return i, t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var r T
|
||||||
|
return -1, r
|
||||||
|
}
|
||||||
|
|
||||||
|
func SearchLast[T any](arr []T, fn func(T) bool) (int, T) {
|
||||||
|
for i := len(arr) - 1; i > 0; i-- {
|
||||||
|
if fn(arr[i]) {
|
||||||
|
return i, arr[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var r T
|
||||||
|
return -1, r
|
||||||
|
}
|
||||||
|
|
||||||
func Filter[T any](arr []T, fn func(T) bool) []T {
|
func Filter[T any](arr []T, fn func(T) bool) []T {
|
||||||
var r []T
|
var r []T
|
||||||
for _, t := range arr {
|
for _, t := range arr {
|
||||||
|
@ -164,3 +193,68 @@ func GroupBy[K comparable, T, V any](a []T, fn func(T) (K, V)) map[K][]V {
|
||||||
func ToAnySlice[T any](a []T) []any {
|
func ToAnySlice[T any](a []T) []any {
|
||||||
return Map(a, helper.ToAny[T])
|
return Map(a, helper.ToAny[T])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill 用指定值填充一个切片
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop 弹出最后一个元素
|
||||||
|
func Pop[T any](a *[]T) T {
|
||||||
|
arr := *a
|
||||||
|
v := arr[len(arr)-1]
|
||||||
|
|
||||||
|
*a = append(arr[:len(arr)-1])
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rand 随机取一个元素
|
||||||
|
func Rand[T any](a []T) (int, T) {
|
||||||
|
i := number.Rand(0, len(a)-1)
|
||||||
|
return i, a[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandPop 随机弹出一个元素并返回那个剩余长度
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift 将切片的第一个单元移出并作为结果返回
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package slice
|
package slice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper/number"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -527,3 +528,315 @@ func TestToAnySlice(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSearchFirst(t *testing.T) {
|
||||||
|
type args[T int] struct {
|
||||||
|
arr []T
|
||||||
|
fn func(T) bool
|
||||||
|
}
|
||||||
|
type testCase[T int] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
want int
|
||||||
|
want1 T
|
||||||
|
}
|
||||||
|
tests := []testCase[int]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[int]{
|
||||||
|
arr: number.Range(1, 10, 1),
|
||||||
|
fn: func(t int) bool {
|
||||||
|
return t == 5
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: 4,
|
||||||
|
want1: 5,
|
||||||
|
}, {
|
||||||
|
name: "t2",
|
||||||
|
args: args[int]{
|
||||||
|
arr: number.Range(1, 10, 1),
|
||||||
|
fn: func(t int) bool {
|
||||||
|
return t == 11
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: -1,
|
||||||
|
want1: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, got1 := SearchFirst(tt.args.arr, tt.args.fn)
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("SearchFirst() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got1, tt.want1) {
|
||||||
|
t.Errorf("SearchFirst() got1 = %v, want %v", got1, tt.want1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSearchLast(t *testing.T) {
|
||||||
|
type args[T int] struct {
|
||||||
|
arr []T
|
||||||
|
fn func(T) bool
|
||||||
|
}
|
||||||
|
type testCase[T int] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
want int
|
||||||
|
want1 T
|
||||||
|
}
|
||||||
|
tests := []testCase[int]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[int]{
|
||||||
|
arr: []int{1, 55, 5, 5, 5, 5, 22},
|
||||||
|
fn: func(t int) bool {
|
||||||
|
return t == 5
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: 5,
|
||||||
|
want1: 5,
|
||||||
|
}, {
|
||||||
|
name: "t2",
|
||||||
|
args: args[int]{
|
||||||
|
arr: number.Range(1, 10, 1),
|
||||||
|
fn: func(t int) bool {
|
||||||
|
return t == 11
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: -1,
|
||||||
|
want1: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, got1 := SearchLast(tt.args.arr, tt.args.fn)
|
||||||
|
if got != tt.want {
|
||||||
|
t.Errorf("SearchLast() got = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got1, tt.want1) {
|
||||||
|
t.Errorf("SearchLast() got1 = %v, want %v", got1, tt.want1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWalk(t *testing.T) {
|
||||||
|
type args[T int] struct {
|
||||||
|
arr []T
|
||||||
|
fn func(*T)
|
||||||
|
}
|
||||||
|
type testCase[T int] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
}
|
||||||
|
tests := []testCase[int]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[int]{
|
||||||
|
arr: number.Range(1, 10, 1),
|
||||||
|
fn: func(i *int) {
|
||||||
|
*i = *i * 2
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
fmt.Println(tt.args.arr)
|
||||||
|
Walk(tt.args.arr, tt.args.fn)
|
||||||
|
fmt.Println(tt.args.arr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
59
helper/slice/slices.go
Normal file
59
helper/slice/slices.go
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func Shuffle[T any](a *[]T) {
|
||||||
|
if len(*a) < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
b := make([]T, 0, len(*a))
|
||||||
|
for {
|
||||||
|
v, l := RandPop(a)
|
||||||
|
b = append(b, v)
|
||||||
|
if l < 1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
*a = b
|
||||||
|
}
|
||||||
|
|
||||||
|
func Delete[T any](a *[]T, index int) {
|
||||||
|
if index >= len(*a) || index < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
arr := *a
|
||||||
|
*a = append(arr[:index], arr[index+1:]...)
|
||||||
|
}
|
136
helper/slice/slices_test.go
Normal file
136
helper/slice/slices_test.go
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestShuffle(t *testing.T) {
|
||||||
|
type args[T int] struct {
|
||||||
|
a *[]T
|
||||||
|
}
|
||||||
|
type testCase[T int] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
}
|
||||||
|
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 < 20; i++ {
|
||||||
|
Shuffle(tt.args.a)
|
||||||
|
fmt.Println(a)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDelete(t *testing.T) {
|
||||||
|
type args[T int] struct {
|
||||||
|
a *[]T
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
type testCase[T int] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
}
|
||||||
|
a := number.Range(1, 5, 1)
|
||||||
|
b := number.Range(1, 5, 1)
|
||||||
|
fmt.Println(a)
|
||||||
|
fmt.Println(b)
|
||||||
|
tests := []testCase[int]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[int]{&a, 0},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "t2",
|
||||||
|
args: args[int]{&b, 2},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
Delete(tt.args.a, tt.args.index)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fmt.Println(a)
|
||||||
|
fmt.Println(b)
|
||||||
|
}
|
|
@ -140,6 +140,7 @@ func (h *indexHandle) parseParams() (err error) {
|
||||||
if category == "" {
|
if category == "" {
|
||||||
category = h.c.Param("tag")
|
category = h.c.Param("tag")
|
||||||
if category != "" {
|
if category != "" {
|
||||||
|
h.scene = plugins.Tag
|
||||||
allNames := cache.AllTagsNames(h.c)
|
allNames := cache.AllTagsNames(h.c)
|
||||||
if _, ok := allNames[category]; !ok {
|
if _, ok := allNames[category]; !ok {
|
||||||
return errors.New(str.Join("not exists tag ", category))
|
return errors.New(str.Join("not exists tag ", category))
|
||||||
|
@ -148,6 +149,7 @@ func (h *indexHandle) parseParams() (err error) {
|
||||||
h.header = fmt.Sprintf("标签: <span>%s</span>", category)
|
h.header = fmt.Sprintf("标签: <span>%s</span>", category)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
h.scene = plugins.Category
|
||||||
allNames := cache.AllCategoryNames(h.c)
|
allNames := cache.AllCategoryNames(h.c)
|
||||||
if _, ok := allNames[category]; !ok {
|
if _, ok := allNames[category]; !ok {
|
||||||
return errors.New(str.Join("not exists category ", category))
|
return errors.New(str.Join("not exists category ", category))
|
||||||
|
@ -189,7 +191,6 @@ func (h *indexHandle) parseParams() (err error) {
|
||||||
"left join", "wp_terms d", "c.term_id=d.term_id",
|
"left join", "wp_terms d", "c.term_id=d.term_id",
|
||||||
})
|
})
|
||||||
h.setTitleLR(category, wpconfig.Options.Value("blogname"))
|
h.setTitleLR(category, wpconfig.Options.Value("blogname"))
|
||||||
h.scene = plugins.Category
|
|
||||||
}
|
}
|
||||||
s := h.c.Query("s")
|
s := h.c.Query("s")
|
||||||
if s != "" && strings.Replace(s, " ", "", -1) != "" {
|
if s != "" && strings.Replace(s, " ", "", -1) != "" {
|
||||||
|
|
|
@ -8,6 +8,7 @@ const (
|
||||||
Home = iota + 1
|
Home = iota + 1
|
||||||
Archive
|
Archive
|
||||||
Category
|
Category
|
||||||
|
Tag
|
||||||
Search
|
Search
|
||||||
Detail
|
Detail
|
||||||
|
|
||||||
|
@ -21,6 +22,7 @@ var IndexSceneMap = map[int]struct{}{
|
||||||
Home: {},
|
Home: {},
|
||||||
Archive: {},
|
Archive: {},
|
||||||
Category: {},
|
Category: {},
|
||||||
|
Tag: {},
|
||||||
Search: {},
|
Search: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
var themeMap = map[string]func(int, *gin.Context, gin.H, int, int){}
|
var themeMap = map[string]func(int, *gin.Context, gin.H, int, int){}
|
||||||
|
|
||||||
func AddThemeHookFunc(name string, fn func(int, *gin.Context, gin.H, int, int)) {
|
func addThemeHookFunc(name string, fn func(int, *gin.Context, gin.H, int, int)) {
|
||||||
if _, ok := themeMap[name]; ok {
|
if _, ok := themeMap[name]; ok {
|
||||||
panic("exists same name theme")
|
panic("exists same name theme")
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ func FuncMap() template.FuncMap {
|
||||||
return comFn
|
return comFn
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddTemplateFunc(fnName string, fn any) {
|
func addTemplateFunc(fnName string, fn any) {
|
||||||
if _, ok := comFn[fnName]; ok {
|
if _, ok := comFn[fnName]; ok {
|
||||||
panic("exists same name func")
|
panic("exists same name func")
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitThemeAndTemplateFuncMap() {
|
func InitThemeAndTemplateFuncMap() {
|
||||||
AddThemeHookFunc(twentyseventeen.ThemeName, twentyseventeen.Hook)
|
addThemeHookFunc(twentyseventeen.ThemeName, twentyseventeen.Hook)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTemplateName() string {
|
func GetTemplateName() string {
|
||||||
|
|
|
@ -64,9 +64,19 @@ func Hook(status int, c *gin.Context, h gin.H, scene, stats int) {
|
||||||
d = 0
|
d = 0
|
||||||
}
|
}
|
||||||
} else if scene == plugins.Category {
|
} else if scene == plugins.Category {
|
||||||
cate := slice.Filter(cache.Categories(c), func(my models.TermsMy) bool {
|
cat := c.Param("category")
|
||||||
return my.Name == c.Param("category")
|
_, cate := slice.SearchFirst(cache.Categories(c), func(my models.TermsMy) bool {
|
||||||
})[0]
|
return my.Name == cat
|
||||||
|
})
|
||||||
|
d = int(cate.Terms.TermId)
|
||||||
|
if cate.Slug[0] != '%' {
|
||||||
|
s = cate.Slug
|
||||||
|
}
|
||||||
|
} else if scene == plugins.Tag {
|
||||||
|
cat := c.Param("tag")
|
||||||
|
_, cate := slice.SearchFirst(cache.Tags(c), func(my models.TermsMy) bool {
|
||||||
|
return my.Name == cat
|
||||||
|
})
|
||||||
d = int(cate.Terms.TermId)
|
d = int(cate.Terms.TermId)
|
||||||
if cate.Slug[0] != '%' {
|
if cate.Slug[0] != '%' {
|
||||||
s = cate.Slug
|
s = cate.Slug
|
||||||
|
@ -175,7 +185,7 @@ func bodyClass(scene, d int, a ...any) string {
|
||||||
} else {
|
} else {
|
||||||
s = "search-no-results"
|
s = "search-no-results"
|
||||||
}
|
}
|
||||||
} else if scene == plugins.Category {
|
} else if scene == plugins.Category || scene == plugins.Tag {
|
||||||
s = fmt.Sprintf("category-%d %v", d, a[0])
|
s = fmt.Sprintf("category-%d %v", d, a[0])
|
||||||
} else if scene == plugins.Detail {
|
} else if scene == plugins.Detail {
|
||||||
s = fmt.Sprintf("postid-%d", d)
|
s = fmt.Sprintf("postid-%d", d)
|
||||||
|
@ -184,6 +194,7 @@ func bodyClass(scene, d int, a ...any) string {
|
||||||
plugins.Home: "home blog ",
|
plugins.Home: "home blog ",
|
||||||
plugins.Archive: "archive date page-two-column",
|
plugins.Archive: "archive date page-two-column",
|
||||||
plugins.Category: str.Join("archive category page-two-column ", s),
|
plugins.Category: str.Join("archive category page-two-column ", s),
|
||||||
|
plugins.Tag: str.Join("archive category page-two-column ", s),
|
||||||
plugins.Search: str.Join("search ", s),
|
plugins.Search: str.Join("search ", s),
|
||||||
plugins.Detail: str.Join("post-template-default single single-post single-format-standard ", s),
|
plugins.Detail: str.Join("post-template-default single single-post single-format-standard ", s),
|
||||||
}[scene]
|
}[scene]
|
||||||
|
|
|
@ -24,11 +24,11 @@ func newMapX[K comparable, V any]() mapX[K, V] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SimpleMapFilterAndMapToSlice[R any, K comparable, V any](mm SimpleMapStream[K, V], fn func(K, V) (R, bool)) SimpleSliceStream[R] {
|
func SimpleMapFilterAndMapToSlice[R any, K comparable, V any](mm MapStream[K, V], fn func(K, V) (R, bool)) Stream[R] {
|
||||||
return NewSimpleSliceStream(maps.FilterToSlice(mm.m, fn))
|
return NewStream(maps.FilterToSlice(mm.m, fn))
|
||||||
}
|
}
|
||||||
|
|
||||||
func SimpleMapParallelFilterAndMapToMap[K comparable, V any, KK comparable, VV any](mm SimpleMapStream[KK, VV], fn func(KK, VV) (K, V, bool), c int) SimpleMapStream[K, V] {
|
func SimpleMapParallelFilterAndMapToMap[K comparable, V any, KK comparable, VV any](mm MapStream[KK, VV], fn func(KK, VV) (K, V, bool), c int) MapStream[K, V] {
|
||||||
m := newMapX[K, V]()
|
m := newMapX[K, V]()
|
||||||
mm.ParallelForEach(func(kk KK, vv VV) {
|
mm.ParallelForEach(func(kk KK, vv VV) {
|
||||||
k, v, ok := fn(kk, vv)
|
k, v, ok := fn(kk, vv)
|
||||||
|
@ -36,11 +36,11 @@ func SimpleMapParallelFilterAndMapToMap[K comparable, V any, KK comparable, VV a
|
||||||
m.set(k, v)
|
m.set(k, v)
|
||||||
}
|
}
|
||||||
}, c)
|
}, c)
|
||||||
return SimpleMapStream[K, V]{m.m}
|
return MapStream[K, V]{m.m}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SimpleMapStreamFilterAndMapToMap[K comparable, V any, KK comparable, VV comparable](a SimpleMapStream[KK, VV], fn func(KK, VV) (K, V, bool)) (r SimpleMapStream[K, V]) {
|
func SimpleMapStreamFilterAndMapToMap[K comparable, V any, KK comparable, VV comparable](a MapStream[KK, VV], fn func(KK, VV) (K, V, bool)) (r MapStream[K, V]) {
|
||||||
r = SimpleMapStream[K, V]{make(map[K]V)}
|
r = MapStream[K, V]{make(map[K]V)}
|
||||||
for k, v := range a.m {
|
for k, v := range a.m {
|
||||||
kk, vv, ok := fn(k, v)
|
kk, vv, ok := fn(k, v)
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -50,21 +50,21 @@ func SimpleMapStreamFilterAndMapToMap[K comparable, V any, KK comparable, VV com
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSimpleMapStream[K comparable, V any](m map[K]V) SimpleMapStream[K, V] {
|
func NewSimpleMapStream[K comparable, V any](m map[K]V) MapStream[K, V] {
|
||||||
return SimpleMapStream[K, V]{m}
|
return MapStream[K, V]{m}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SimpleMapStream[K comparable, V any] struct {
|
type MapStream[K comparable, V any] struct {
|
||||||
m map[K]V
|
m map[K]V
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r SimpleMapStream[K, V]) ForEach(fn func(K, V)) {
|
func (r MapStream[K, V]) ForEach(fn func(K, V)) {
|
||||||
for k, v := range r.m {
|
for k, v := range r.m {
|
||||||
fn(k, v)
|
fn(k, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r SimpleMapStream[K, V]) ParallelForEach(fn func(K, V), c int) {
|
func (r MapStream[K, V]) ParallelForEach(fn func(K, V), c int) {
|
||||||
p := taskPools.NewPools(c)
|
p := taskPools.NewPools(c)
|
||||||
for k, v := range r.m {
|
for k, v := range r.m {
|
||||||
k := k
|
k := k
|
||||||
|
@ -76,10 +76,10 @@ func (r SimpleMapStream[K, V]) ParallelForEach(fn func(K, V), c int) {
|
||||||
p.Wait()
|
p.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r SimpleMapStream[K, V]) Len() int {
|
func (r MapStream[K, V]) Len() int {
|
||||||
return len(r.m)
|
return len(r.m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r SimpleMapStream[K, V]) Result() map[K]V {
|
func (r MapStream[K, V]) Result() map[K]V {
|
||||||
return r.m
|
return r.m
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,13 @@ func TestNewSimpleMapStream(t *testing.T) {
|
||||||
type testCase[K int, V int] struct {
|
type testCase[K int, V int] struct {
|
||||||
name string
|
name string
|
||||||
args args[K, V]
|
args args[K, V]
|
||||||
want SimpleMapStream[K, V]
|
want MapStream[K, V]
|
||||||
}
|
}
|
||||||
tests := []testCase[int, int]{
|
tests := []testCase[int, int]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args[int, int]{make(map[int]int)},
|
args: args[int, int]{make(map[int]int)},
|
||||||
want: SimpleMapStream[int, int]{make(map[int]int)},
|
want: MapStream[int, int]{make(map[int]int)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -41,14 +41,14 @@ var w = slice.ToMap(y, func(v int) (int, int) {
|
||||||
|
|
||||||
func TestSimpleMapFilterAndMapToSlice(t *testing.T) {
|
func TestSimpleMapFilterAndMapToSlice(t *testing.T) {
|
||||||
type args[K int, V int, R int] struct {
|
type args[K int, V int, R int] struct {
|
||||||
mm SimpleMapStream[K, V]
|
mm MapStream[K, V]
|
||||||
fn func(K, V) (R, bool)
|
fn func(K, V) (R, bool)
|
||||||
c int
|
c int
|
||||||
}
|
}
|
||||||
type testCase[K int, V int, R int] struct {
|
type testCase[K int, V int, R int] struct {
|
||||||
name string
|
name string
|
||||||
args args[K, V, R]
|
args args[K, V, R]
|
||||||
want SimpleSliceStream[R]
|
want Stream[R]
|
||||||
}
|
}
|
||||||
tests := []testCase[int, int, int]{
|
tests := []testCase[int, int, int]{
|
||||||
{
|
{
|
||||||
|
@ -63,7 +63,7 @@ func TestSimpleMapFilterAndMapToSlice(t *testing.T) {
|
||||||
},
|
},
|
||||||
c: 6,
|
c: 6,
|
||||||
},
|
},
|
||||||
want: NewSimpleSliceStream(y[500:]),
|
want: NewStream(y[500:]),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -79,14 +79,14 @@ func TestSimpleMapFilterAndMapToSlice(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleMapParallelFilterAndMapToMap(t *testing.T) {
|
func TestSimpleMapParallelFilterAndMapToMap(t *testing.T) {
|
||||||
type args[KK string, VV string, K int, V int] struct {
|
type args[KK string, VV string, K int, V int] struct {
|
||||||
mm SimpleMapStream[K, V]
|
mm MapStream[K, V]
|
||||||
fn func(K, V) (KK, VV, bool)
|
fn func(K, V) (KK, VV, bool)
|
||||||
c int
|
c int
|
||||||
}
|
}
|
||||||
type testCase[KK string, VV string, K int, V int] struct {
|
type testCase[KK string, VV string, K int, V int] struct {
|
||||||
name string
|
name string
|
||||||
args args[KK, VV, K, V]
|
args args[KK, VV, K, V]
|
||||||
want SimpleMapStream[KK, VV]
|
want MapStream[KK, VV]
|
||||||
}
|
}
|
||||||
tests := []testCase[string, string, int, int]{
|
tests := []testCase[string, string, int, int]{
|
||||||
{
|
{
|
||||||
|
@ -119,13 +119,13 @@ func TestSimpleMapParallelFilterAndMapToMap(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleMapStreamFilterAndMapToMap(t *testing.T) {
|
func TestSimpleMapStreamFilterAndMapToMap(t *testing.T) {
|
||||||
type args[KK string, VV string, K int, V int] struct {
|
type args[KK string, VV string, K int, V int] struct {
|
||||||
a SimpleMapStream[K, V]
|
a MapStream[K, V]
|
||||||
fn func(K, V) (KK, VV, bool)
|
fn func(K, V) (KK, VV, bool)
|
||||||
}
|
}
|
||||||
type testCase[KK string, VV string, K int, V int] struct {
|
type testCase[KK string, VV string, K int, V int] struct {
|
||||||
name string
|
name string
|
||||||
args args[KK, VV, K, V]
|
args args[KK, VV, K, V]
|
||||||
wantR SimpleMapStream[KK, VV]
|
wantR MapStream[KK, VV]
|
||||||
}
|
}
|
||||||
tests := []testCase[string, string, int, int]{
|
tests := []testCase[string, string, int, int]{
|
||||||
{
|
{
|
||||||
|
@ -161,7 +161,7 @@ func TestSimpleMapStream_ForEach(t *testing.T) {
|
||||||
}
|
}
|
||||||
type testCase[K int, V int] struct {
|
type testCase[K int, V int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleMapStream[K, V]
|
r MapStream[K, V]
|
||||||
args args[K, V]
|
args args[K, V]
|
||||||
}
|
}
|
||||||
tests := []testCase[int, int]{
|
tests := []testCase[int, int]{
|
||||||
|
@ -187,7 +187,7 @@ func TestSimpleMapStream_ForEach(t *testing.T) {
|
||||||
func TestSimpleMapStream_Len(t *testing.T) {
|
func TestSimpleMapStream_Len(t *testing.T) {
|
||||||
type testCase[K int, V int] struct {
|
type testCase[K int, V int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleMapStream[K, V]
|
r MapStream[K, V]
|
||||||
want int
|
want int
|
||||||
}
|
}
|
||||||
tests := []testCase[int, int]{
|
tests := []testCase[int, int]{
|
||||||
|
@ -213,7 +213,7 @@ func TestSimpleMapStream_ParallelForEach(t *testing.T) {
|
||||||
}
|
}
|
||||||
type testCase[K int, V int] struct {
|
type testCase[K int, V int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleMapStream[K, V]
|
r MapStream[K, V]
|
||||||
args args[K, V]
|
args args[K, V]
|
||||||
}
|
}
|
||||||
tests := []testCase[int, int]{
|
tests := []testCase[int, int]{
|
||||||
|
@ -238,7 +238,7 @@ func TestSimpleMapStream_ParallelForEach(t *testing.T) {
|
||||||
func TestSimpleMapStream_Result(t *testing.T) {
|
func TestSimpleMapStream_Result(t *testing.T) {
|
||||||
type testCase[K int, V int] struct {
|
type testCase[K int, V int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleMapStream[K, V]
|
r MapStream[K, V]
|
||||||
want map[K]V
|
want map[K]V
|
||||||
}
|
}
|
||||||
tests := []testCase[int, int]{
|
tests := []testCase[int, int]{
|
||||||
|
|
|
@ -1,149 +0,0 @@
|
||||||
package stream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/fthvgb1/wp-go/helper/slice"
|
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
|
||||||
"github.com/fthvgb1/wp-go/taskPools"
|
|
||||||
)
|
|
||||||
|
|
||||||
func SimpleParallelFilterAndMap[R, T any](a SimpleSliceStream[T], fn func(T) (R, bool), c int) SimpleSliceStream[R] {
|
|
||||||
var x []R
|
|
||||||
rr := safety.NewSlice(x)
|
|
||||||
a.ParallelForEach(func(t T) {
|
|
||||||
y, ok := fn(t)
|
|
||||||
if ok {
|
|
||||||
rr.Append(y)
|
|
||||||
}
|
|
||||||
}, c)
|
|
||||||
return SimpleSliceStream[R]{rr.Load()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func SimpleParallelFilterAndMapToMap[K comparable, V any, T any](a SimpleSliceStream[T], fn func(t T) (K, V, bool), c int) (r SimpleMapStream[K, V]) {
|
|
||||||
m := newMapX[K, V]()
|
|
||||||
a.ParallelForEach(func(t T) {
|
|
||||||
k, v, ok := fn(t)
|
|
||||||
if ok {
|
|
||||||
m.set(k, v)
|
|
||||||
}
|
|
||||||
}, c)
|
|
||||||
var mm = map[K]V{}
|
|
||||||
r = NewSimpleMapStream(mm)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func SimpleSliceFilterAndMapToMap[K comparable, V any, T any](a SimpleSliceStream[T], fn func(t T) (K, V, bool), isCoverPrev bool) (r SimpleMapStream[K, V]) {
|
|
||||||
m := make(map[K]V)
|
|
||||||
a.ForEach(func(t T) {
|
|
||||||
k, v, ok := fn(t)
|
|
||||||
if ok {
|
|
||||||
_, ok = m[k]
|
|
||||||
if isCoverPrev || !ok {
|
|
||||||
m[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
r.m = m
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func SimpleStreamFilterAndMap[R, T any](a SimpleSliceStream[T], fn func(T) (R, bool)) SimpleSliceStream[R] {
|
|
||||||
return NewSimpleSliceStream(slice.FilterAndMap(a.arr, fn))
|
|
||||||
}
|
|
||||||
|
|
||||||
func SimpleParallelMap[R, T any](a SimpleSliceStream[T], fn func(T) R, c int) SimpleSliceStream[R] {
|
|
||||||
var x []R
|
|
||||||
rr := safety.NewSlice(x)
|
|
||||||
a.ParallelForEach(func(t T) {
|
|
||||||
rr.Append(fn(t))
|
|
||||||
}, c)
|
|
||||||
return SimpleSliceStream[R]{rr.Load()}
|
|
||||||
}
|
|
||||||
func SimpleStreamMap[R, T any](a SimpleSliceStream[T], fn func(T) R) SimpleSliceStream[R] {
|
|
||||||
return NewSimpleSliceStream(slice.Map(a.arr, fn))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Reduce[T any, S any](s SimpleSliceStream[S], fn func(S, T) T, init T) (r T) {
|
|
||||||
return slice.Reduce(s.arr, fn, init)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSimpleSliceStream[T any](arr []T) SimpleSliceStream[T] {
|
|
||||||
return SimpleSliceStream[T]{arr: arr}
|
|
||||||
}
|
|
||||||
|
|
||||||
type SimpleSliceStream[T any] struct {
|
|
||||||
arr []T
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) ForEach(fn func(T)) {
|
|
||||||
for _, t := range r.arr {
|
|
||||||
fn(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) ParallelForEach(fn func(T), c int) {
|
|
||||||
p := taskPools.NewPools(c)
|
|
||||||
for _, t := range r.arr {
|
|
||||||
t := t
|
|
||||||
p.Execute(func() {
|
|
||||||
fn(t)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
p.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) ParallelFilter(fn func(T) bool, c int) SimpleSliceStream[T] {
|
|
||||||
rr := safety.NewSlice([]T{})
|
|
||||||
r.ParallelForEach(func(t T) {
|
|
||||||
if fn(t) {
|
|
||||||
rr.Append(t)
|
|
||||||
}
|
|
||||||
}, c)
|
|
||||||
return SimpleSliceStream[T]{rr.Load()}
|
|
||||||
}
|
|
||||||
func (r SimpleSliceStream[T]) Filter(fn func(T) bool) SimpleSliceStream[T] {
|
|
||||||
r.arr = slice.Filter(r.arr, fn)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) ParallelMap(fn func(T) T, c int) SimpleSliceStream[T] {
|
|
||||||
rr := safety.NewSlice([]T{})
|
|
||||||
r.ParallelForEach(func(t T) {
|
|
||||||
rr.Append(fn(t))
|
|
||||||
}, c)
|
|
||||||
return SimpleSliceStream[T]{rr.Load()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) Map(fn func(T) T) SimpleSliceStream[T] {
|
|
||||||
r.arr = slice.Map(r.arr, fn)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) Sort(fn func(i, j T) bool) SimpleSliceStream[T] {
|
|
||||||
slice.SortSelf(r.arr, fn)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) Len() int {
|
|
||||||
return len(r.arr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) Limit(limit, offset int) SimpleSliceStream[T] {
|
|
||||||
l := len(r.arr)
|
|
||||||
if offset >= l {
|
|
||||||
return SimpleSliceStream[T]{}
|
|
||||||
}
|
|
||||||
ll := offset + limit
|
|
||||||
if ll > l {
|
|
||||||
ll = l
|
|
||||||
}
|
|
||||||
return SimpleSliceStream[T]{r.arr[offset:ll]}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) Reverse() SimpleSliceStream[T] {
|
|
||||||
slice.ReverseSelf(r.arr)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) Result() []T {
|
|
||||||
return r.arr
|
|
||||||
}
|
|
149
stream/stream.go
Normal file
149
stream/stream.go
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
package stream
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
|
"github.com/fthvgb1/wp-go/taskPools"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParallelFilterAndMap[R, T any](a Stream[T], fn func(T) (R, bool), c int) Stream[R] {
|
||||||
|
var x []R
|
||||||
|
rr := safety.NewSlice(x)
|
||||||
|
a.ParallelForEach(func(t T) {
|
||||||
|
y, ok := fn(t)
|
||||||
|
if ok {
|
||||||
|
rr.Append(y)
|
||||||
|
}
|
||||||
|
}, c)
|
||||||
|
return Stream[R]{rr.Load()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParallelFilterAndMapToMapStream[K comparable, V any, T any](a Stream[T], fn func(t T) (K, V, bool), c int) (r MapStream[K, V]) {
|
||||||
|
m := newMapX[K, V]()
|
||||||
|
a.ParallelForEach(func(t T) {
|
||||||
|
k, v, ok := fn(t)
|
||||||
|
if ok {
|
||||||
|
m.set(k, v)
|
||||||
|
}
|
||||||
|
}, c)
|
||||||
|
var mm = map[K]V{}
|
||||||
|
r = NewSimpleMapStream(mm)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceFilterAndMapToMapStream[K comparable, V any, T any](a Stream[T], fn func(t T) (K, V, bool), isCoverPrev bool) (r MapStream[K, V]) {
|
||||||
|
m := make(map[K]V)
|
||||||
|
a.ForEach(func(t T) {
|
||||||
|
k, v, ok := fn(t)
|
||||||
|
if ok {
|
||||||
|
_, ok = m[k]
|
||||||
|
if isCoverPrev || !ok {
|
||||||
|
m[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
r.m = m
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func FilterAndMapNewStream[R, T any](a Stream[T], fn func(T) (R, bool)) Stream[R] {
|
||||||
|
return NewStream(slice.FilterAndMap(a.arr, fn))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParallelMap[R, T any](a Stream[T], fn func(T) R, c int) Stream[R] {
|
||||||
|
var x []R
|
||||||
|
rr := safety.NewSlice(x)
|
||||||
|
a.ParallelForEach(func(t T) {
|
||||||
|
rr.Append(fn(t))
|
||||||
|
}, c)
|
||||||
|
return Stream[R]{rr.Load()}
|
||||||
|
}
|
||||||
|
func MapNewStream[R, T any](a Stream[T], fn func(T) R) Stream[R] {
|
||||||
|
return NewStream(slice.Map(a.arr, fn))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Reduce[T any, S any](s Stream[S], fn func(S, T) T, init T) (r T) {
|
||||||
|
return slice.Reduce(s.arr, fn, init)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStream[T any](arr []T) Stream[T] {
|
||||||
|
return Stream[T]{arr: arr}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stream[T any] struct {
|
||||||
|
arr []T
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Stream[T]) ForEach(fn func(T)) {
|
||||||
|
for _, t := range r.arr {
|
||||||
|
fn(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Stream[T]) ParallelForEach(fn func(T), c int) {
|
||||||
|
p := taskPools.NewPools(c)
|
||||||
|
for _, t := range r.arr {
|
||||||
|
t := t
|
||||||
|
p.Execute(func() {
|
||||||
|
fn(t)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
p.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Stream[T]) ParallelFilter(fn func(T) bool, c int) Stream[T] {
|
||||||
|
rr := safety.NewSlice([]T{})
|
||||||
|
r.ParallelForEach(func(t T) {
|
||||||
|
if fn(t) {
|
||||||
|
rr.Append(t)
|
||||||
|
}
|
||||||
|
}, c)
|
||||||
|
return Stream[T]{rr.Load()}
|
||||||
|
}
|
||||||
|
func (r Stream[T]) Filter(fn func(T) bool) Stream[T] {
|
||||||
|
r.arr = slice.Filter(r.arr, fn)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Stream[T]) ParallelMap(fn func(T) T, c int) Stream[T] {
|
||||||
|
rr := safety.NewSlice([]T{})
|
||||||
|
r.ParallelForEach(func(t T) {
|
||||||
|
rr.Append(fn(t))
|
||||||
|
}, c)
|
||||||
|
return Stream[T]{rr.Load()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Stream[T]) Map(fn func(T) T) Stream[T] {
|
||||||
|
r.arr = slice.Map(r.arr, fn)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Stream[T]) Sort(fn func(i, j T) bool) Stream[T] {
|
||||||
|
slice.SortSelf(r.arr, fn)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Stream[T]) Len() int {
|
||||||
|
return len(r.arr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Stream[T]) Limit(limit, offset int) Stream[T] {
|
||||||
|
l := len(r.arr)
|
||||||
|
if offset >= l {
|
||||||
|
return Stream[T]{}
|
||||||
|
}
|
||||||
|
ll := offset + limit
|
||||||
|
if ll > l {
|
||||||
|
ll = l
|
||||||
|
}
|
||||||
|
return Stream[T]{r.arr[offset:ll]}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Stream[T]) Reverse() Stream[T] {
|
||||||
|
slice.ReverseSelf(r.arr)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r Stream[T]) Result() []T {
|
||||||
|
return r.arr
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var s = NewSimpleSliceStream(number.Range(1, 10, 1))
|
var s = NewStream(number.Range(1, 10, 1))
|
||||||
|
|
||||||
func TestSimpleSliceStream_Filter(t *testing.T) {
|
func TestSimpleSliceStream_Filter(t *testing.T) {
|
||||||
type args[T int] struct {
|
type args[T int] struct {
|
||||||
|
@ -17,9 +17,9 @@ func TestSimpleSliceStream_Filter(t *testing.T) {
|
||||||
}
|
}
|
||||||
type testCase[T int] struct {
|
type testCase[T int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleSliceStream[T]
|
r Stream[T]
|
||||||
args args[T]
|
args args[T]
|
||||||
want SimpleSliceStream[T]
|
want Stream[T]
|
||||||
}
|
}
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@ func TestSimpleSliceStream_Filter(t *testing.T) {
|
||||||
return
|
return
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{number.Range(6, 10, 1)},
|
want: Stream[int]{number.Range(6, 10, 1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -51,7 +51,7 @@ func TestSimpleSliceStream_ForEach(t *testing.T) {
|
||||||
}
|
}
|
||||||
type testCase[T int] struct {
|
type testCase[T int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleSliceStream[T]
|
r Stream[T]
|
||||||
args args[T]
|
args args[T]
|
||||||
}
|
}
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
|
@ -79,9 +79,9 @@ func TestSimpleSliceStream_Limit(t *testing.T) {
|
||||||
}
|
}
|
||||||
type testCase[T int] struct {
|
type testCase[T int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleSliceStream[T]
|
r Stream[T]
|
||||||
args args
|
args args
|
||||||
want SimpleSliceStream[T]
|
want Stream[T]
|
||||||
}
|
}
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
{
|
{
|
||||||
|
@ -91,7 +91,7 @@ func TestSimpleSliceStream_Limit(t *testing.T) {
|
||||||
limit: 3,
|
limit: 3,
|
||||||
offset: 5,
|
offset: 5,
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{number.Range(6, 8, 1)},
|
want: Stream[int]{number.Range(6, 8, 1)},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "t2",
|
name: "t2",
|
||||||
|
@ -100,7 +100,7 @@ func TestSimpleSliceStream_Limit(t *testing.T) {
|
||||||
limit: 3,
|
limit: 3,
|
||||||
offset: 9,
|
offset: 9,
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{number.Range(10, 10, 1)},
|
want: Stream[int]{number.Range(10, 10, 1)},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "t3",
|
name: "t3",
|
||||||
|
@ -109,7 +109,7 @@ func TestSimpleSliceStream_Limit(t *testing.T) {
|
||||||
limit: 3,
|
limit: 3,
|
||||||
offset: 11,
|
offset: 11,
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{},
|
want: Stream[int]{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -127,9 +127,9 @@ func TestSimpleSliceStream_Map(t *testing.T) {
|
||||||
}
|
}
|
||||||
type testCase[T int] struct {
|
type testCase[T int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleSliceStream[T]
|
r Stream[T]
|
||||||
args args[T]
|
args args[T]
|
||||||
want SimpleSliceStream[T]
|
want Stream[T]
|
||||||
}
|
}
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
{
|
{
|
||||||
|
@ -140,13 +140,13 @@ func TestSimpleSliceStream_Map(t *testing.T) {
|
||||||
return t * 2
|
return t * 2
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{number.Range(2, 20, 2)},
|
want: Stream[int]{number.Range(2, 20, 2)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if got := tt.r.Map(tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
if got := tt.r.Map(tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("Map() = %v, want %v", got, tt.want)
|
t.Errorf("MapNewStream() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ func TestSimpleSliceStream_Map(t *testing.T) {
|
||||||
func TestSimpleSliceStream_Result(t *testing.T) {
|
func TestSimpleSliceStream_Result(t *testing.T) {
|
||||||
type testCase[T int] struct {
|
type testCase[T int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleSliceStream[T]
|
r Stream[T]
|
||||||
want []T
|
want []T
|
||||||
}
|
}
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
|
@ -180,9 +180,9 @@ func TestSimpleSliceStream_Sort(t *testing.T) {
|
||||||
}
|
}
|
||||||
type testCase[T int] struct {
|
type testCase[T int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleSliceStream[T]
|
r Stream[T]
|
||||||
args args[T]
|
args args[T]
|
||||||
want SimpleSliceStream[T]
|
want Stream[T]
|
||||||
}
|
}
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
{
|
{
|
||||||
|
@ -193,7 +193,7 @@ func TestSimpleSliceStream_Sort(t *testing.T) {
|
||||||
return i > j
|
return i > j
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{number.Range(10, 1, -1)},
|
want: Stream[int]{number.Range(10, 1, -1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -212,7 +212,7 @@ func TestSimpleSliceStream_parallelForEach(t *testing.T) {
|
||||||
}
|
}
|
||||||
type testCase[T int] struct {
|
type testCase[T int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleSliceStream[T]
|
r Stream[T]
|
||||||
args args[T]
|
args args[T]
|
||||||
}
|
}
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
|
@ -241,9 +241,9 @@ func TestSimpleSliceStream_ParallelFilter(t *testing.T) {
|
||||||
}
|
}
|
||||||
type testCase[T int] struct {
|
type testCase[T int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleSliceStream[T]
|
r Stream[T]
|
||||||
args args[T]
|
args args[T]
|
||||||
want SimpleSliceStream[T]
|
want Stream[T]
|
||||||
}
|
}
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
{
|
{
|
||||||
|
@ -255,7 +255,7 @@ func TestSimpleSliceStream_ParallelFilter(t *testing.T) {
|
||||||
},
|
},
|
||||||
c: 6,
|
c: 6,
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{number.Range(4, 10, 1)},
|
want: Stream[int]{number.Range(4, 10, 1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -276,9 +276,9 @@ func TestSimpleSliceStream_ParallelMap(t *testing.T) {
|
||||||
}
|
}
|
||||||
type testCase[T int] struct {
|
type testCase[T int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleSliceStream[T]
|
r Stream[T]
|
||||||
args args[T]
|
args args[T]
|
||||||
want SimpleSliceStream[T]
|
want Stream[T]
|
||||||
}
|
}
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
{
|
{
|
||||||
|
@ -290,7 +290,7 @@ func TestSimpleSliceStream_ParallelMap(t *testing.T) {
|
||||||
},
|
},
|
||||||
c: 6,
|
c: 6,
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{number.Range(2, 20, 2)},
|
want: Stream[int]{number.Range(2, 20, 2)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -298,7 +298,7 @@ func TestSimpleSliceStream_ParallelMap(t *testing.T) {
|
||||||
if got := tt.r.ParallelMap(tt.args.fn, tt.args.c).Sort(func(i, j int) bool {
|
if got := tt.r.ParallelMap(tt.args.fn, tt.args.c).Sort(func(i, j int) bool {
|
||||||
return i < j
|
return i < j
|
||||||
}); !reflect.DeepEqual(got, tt.want) {
|
}); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SimpleParallelMap() = %v, want %v", got, tt.want)
|
t.Errorf("ParallelMap() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -306,7 +306,7 @@ func TestSimpleSliceStream_ParallelMap(t *testing.T) {
|
||||||
|
|
||||||
func TestReduce(t *testing.T) {
|
func TestReduce(t *testing.T) {
|
||||||
type args[S, T int] struct {
|
type args[S, T int] struct {
|
||||||
s SimpleSliceStream[S]
|
s Stream[S]
|
||||||
fn func(S, T) T
|
fn func(S, T) T
|
||||||
init T
|
init T
|
||||||
}
|
}
|
||||||
|
@ -339,14 +339,14 @@ func TestReduce(t *testing.T) {
|
||||||
func TestSimpleSliceStream_Reverse(t *testing.T) {
|
func TestSimpleSliceStream_Reverse(t *testing.T) {
|
||||||
type testCase[T int] struct {
|
type testCase[T int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleSliceStream[T]
|
r Stream[T]
|
||||||
want SimpleSliceStream[T]
|
want Stream[T]
|
||||||
}
|
}
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
r: NewSimpleSliceStream(number.Range(1, 10, 1)),
|
r: NewStream(number.Range(1, 10, 1)),
|
||||||
want: SimpleSliceStream[int]{number.Range(10, 1, -1)},
|
want: Stream[int]{number.Range(10, 1, -1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -362,30 +362,30 @@ var x = number.Range(1, 100000, 1)
|
||||||
|
|
||||||
func TestSimpleStreamMap(t *testing.T) {
|
func TestSimpleStreamMap(t *testing.T) {
|
||||||
type args[T int, R string] struct {
|
type args[T int, R string] struct {
|
||||||
a SimpleSliceStream[T]
|
a Stream[T]
|
||||||
fn func(T) R
|
fn func(T) R
|
||||||
}
|
}
|
||||||
type testCase[T int, R string] struct {
|
type testCase[T int, R string] struct {
|
||||||
name string
|
name string
|
||||||
args args[T, R]
|
args args[T, R]
|
||||||
want SimpleSliceStream[R]
|
want Stream[R]
|
||||||
}
|
}
|
||||||
tests := []testCase[int, string]{
|
tests := []testCase[int, string]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args[int, string]{
|
args: args[int, string]{
|
||||||
a: NewSimpleSliceStream(x),
|
a: NewStream(x),
|
||||||
fn: strconv.Itoa,
|
fn: strconv.Itoa,
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[string]{
|
want: Stream[string]{
|
||||||
slice.Map(x, strconv.Itoa),
|
slice.Map(x, strconv.Itoa),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if got := SimpleStreamMap(tt.args.a, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
if got := MapNewStream(tt.args.a, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SimpleStreamMap() = %v, want %v", got, tt.want)
|
t.Errorf("MapNewStream() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -393,36 +393,36 @@ func TestSimpleStreamMap(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleParallelMap(t *testing.T) {
|
func TestSimpleParallelMap(t *testing.T) {
|
||||||
type args[T string, R int] struct {
|
type args[T string, R int] struct {
|
||||||
a SimpleSliceStream[string]
|
a Stream[string]
|
||||||
fn func(T) R
|
fn func(T) R
|
||||||
c int
|
c int
|
||||||
}
|
}
|
||||||
type testCase[T string, R int] struct {
|
type testCase[T string, R int] struct {
|
||||||
name string
|
name string
|
||||||
args args[T, R]
|
args args[T, R]
|
||||||
want SimpleSliceStream[R]
|
want Stream[R]
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []testCase[string, int]{
|
tests := []testCase[string, int]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args[string, int]{
|
args: args[string, int]{
|
||||||
a: NewSimpleSliceStream(slice.Map(x, strconv.Itoa)),
|
a: NewStream(slice.Map(x, strconv.Itoa)),
|
||||||
fn: func(s string) int {
|
fn: func(s string) int {
|
||||||
i, _ := strconv.Atoi(s)
|
i, _ := strconv.Atoi(s)
|
||||||
return i
|
return i
|
||||||
},
|
},
|
||||||
c: 6,
|
c: 6,
|
||||||
},
|
},
|
||||||
want: NewSimpleSliceStream(x),
|
want: NewStream(x),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if got := SimpleParallelMap(tt.args.a, tt.args.fn, tt.args.c).Sort(func(i, j int) bool {
|
if got := ParallelMap(tt.args.a, tt.args.fn, tt.args.c).Sort(func(i, j int) bool {
|
||||||
return i < j
|
return i < j
|
||||||
}); !reflect.DeepEqual(got, tt.want) {
|
}); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SimpleParallelMap() = %v, want %v", got, tt.want)
|
t.Errorf("ParallelMap() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -430,20 +430,20 @@ func TestSimpleParallelMap(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleParallelFilterAndMap(t *testing.T) {
|
func TestSimpleParallelFilterAndMap(t *testing.T) {
|
||||||
type args[T string, R int] struct {
|
type args[T string, R int] struct {
|
||||||
a SimpleSliceStream[string]
|
a Stream[string]
|
||||||
fn func(T) (R, bool)
|
fn func(T) (R, bool)
|
||||||
c int
|
c int
|
||||||
}
|
}
|
||||||
type testCase[T string, R int] struct {
|
type testCase[T string, R int] struct {
|
||||||
name string
|
name string
|
||||||
args args[T, R]
|
args args[T, R]
|
||||||
want SimpleSliceStream[R]
|
want Stream[R]
|
||||||
}
|
}
|
||||||
tests := []testCase[string, int]{
|
tests := []testCase[string, int]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args[string, int]{
|
args: args[string, int]{
|
||||||
a: NewSimpleSliceStream(slice.Map(x, strconv.Itoa)),
|
a: NewStream(slice.Map(x, strconv.Itoa)),
|
||||||
fn: func(s string) (int, bool) {
|
fn: func(s string) (int, bool) {
|
||||||
i, _ := strconv.Atoi(s)
|
i, _ := strconv.Atoi(s)
|
||||||
if i > 50000 {
|
if i > 50000 {
|
||||||
|
@ -453,15 +453,15 @@ func TestSimpleParallelFilterAndMap(t *testing.T) {
|
||||||
},
|
},
|
||||||
c: 6,
|
c: 6,
|
||||||
},
|
},
|
||||||
want: NewSimpleSliceStream(x[50000:]),
|
want: NewStream(x[50000:]),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if got := SimpleParallelFilterAndMap(tt.args.a, tt.args.fn, tt.args.c).Sort(func(i, j int) bool {
|
if got := ParallelFilterAndMap(tt.args.a, tt.args.fn, tt.args.c).Sort(func(i, j int) bool {
|
||||||
return i < j
|
return i < j
|
||||||
}); !reflect.DeepEqual(got, tt.want) {
|
}); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SimpleParallelFilterAndMap() = %v, want %v", got, tt.want)
|
t.Errorf("ParallelFilterAndMap() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -469,19 +469,19 @@ func TestSimpleParallelFilterAndMap(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleStreamFilterAndMap(t *testing.T) {
|
func TestSimpleStreamFilterAndMap(t *testing.T) {
|
||||||
type args[T string, R int] struct {
|
type args[T string, R int] struct {
|
||||||
a SimpleSliceStream[T]
|
a Stream[T]
|
||||||
fn func(T) (R, bool)
|
fn func(T) (R, bool)
|
||||||
}
|
}
|
||||||
type testCase[T any, R any] struct {
|
type testCase[T any, R any] struct {
|
||||||
name string
|
name string
|
||||||
args args[string, int]
|
args args[string, int]
|
||||||
want SimpleSliceStream[R]
|
want Stream[R]
|
||||||
}
|
}
|
||||||
tests := []testCase[string, int]{
|
tests := []testCase[string, int]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args[string, int]{
|
args: args[string, int]{
|
||||||
a: NewSimpleSliceStream(slice.Map(x, strconv.Itoa)),
|
a: NewStream(slice.Map(x, strconv.Itoa)),
|
||||||
fn: func(s string) (int, bool) {
|
fn: func(s string) (int, bool) {
|
||||||
i, _ := strconv.Atoi(s)
|
i, _ := strconv.Atoi(s)
|
||||||
if i > 50000 {
|
if i > 50000 {
|
||||||
|
@ -490,13 +490,13 @@ func TestSimpleStreamFilterAndMap(t *testing.T) {
|
||||||
return 0, false
|
return 0, false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: NewSimpleSliceStream(x[50000:]),
|
want: NewStream(x[50000:]),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if got := SimpleStreamFilterAndMap(tt.args.a, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
if got := FilterAndMapNewStream(tt.args.a, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SimpleStreamFilterAndMap() = %v, want %v", got, tt.want)
|
t.Errorf("FilterAndMapNewStream() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -505,7 +505,7 @@ func TestSimpleStreamFilterAndMap(t *testing.T) {
|
||||||
func TestSimpleSliceStream_Len(t *testing.T) {
|
func TestSimpleSliceStream_Len(t *testing.T) {
|
||||||
type testCase[T int] struct {
|
type testCase[T int] struct {
|
||||||
name string
|
name string
|
||||||
r SimpleSliceStream[T]
|
r Stream[T]
|
||||||
want int
|
want int
|
||||||
}
|
}
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
|
@ -526,20 +526,20 @@ func TestSimpleSliceStream_Len(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleParallelFilterAndMapToMap(t *testing.T) {
|
func TestSimpleParallelFilterAndMapToMap(t *testing.T) {
|
||||||
type args[T int, K int, V int] struct {
|
type args[T int, K int, V int] struct {
|
||||||
a SimpleSliceStream[V]
|
a Stream[V]
|
||||||
fn func(t T) (K, V, bool)
|
fn func(t T) (K, V, bool)
|
||||||
c int
|
c int
|
||||||
}
|
}
|
||||||
type testCase[T int, K int, V int] struct {
|
type testCase[T int, K int, V int] struct {
|
||||||
name string
|
name string
|
||||||
args args[T, K, V]
|
args args[T, K, V]
|
||||||
wantR SimpleMapStream[K, V]
|
wantR MapStream[K, V]
|
||||||
}
|
}
|
||||||
tests := []testCase[int, int, int]{
|
tests := []testCase[int, int, int]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args[int, int, int]{
|
args: args[int, int, int]{
|
||||||
a: NewSimpleSliceStream(x),
|
a: NewStream(x),
|
||||||
fn: func(v int) (int, int, bool) {
|
fn: func(v int) (int, int, bool) {
|
||||||
if v >= 50000 {
|
if v >= 50000 {
|
||||||
return v, v, true
|
return v, v, true
|
||||||
|
@ -555,8 +555,8 @@ func TestSimpleParallelFilterAndMapToMap(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if gotR := SimpleParallelFilterAndMapToMap(tt.args.a, tt.args.fn, tt.args.c); !reflect.DeepEqual(gotR, tt.wantR) {
|
if gotR := ParallelFilterAndMapToMapStream(tt.args.a, tt.args.fn, tt.args.c); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
t.Errorf("SimpleParallelFilterAndMapToMap() = %v, want %v", gotR, tt.wantR)
|
t.Errorf("ParallelFilterAndMapToMapStream() = %v, want %v", gotR, tt.wantR)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -564,20 +564,20 @@ func TestSimpleParallelFilterAndMapToMap(t *testing.T) {
|
||||||
|
|
||||||
func TestSimpleSliceFilterAndMapToMap(t *testing.T) {
|
func TestSimpleSliceFilterAndMapToMap(t *testing.T) {
|
||||||
type args[T int, K int, V int] struct {
|
type args[T int, K int, V int] struct {
|
||||||
a SimpleSliceStream[T]
|
a Stream[T]
|
||||||
fn func(t T) (K, V, bool)
|
fn func(t T) (K, V, bool)
|
||||||
isCoverPrev bool
|
isCoverPrev bool
|
||||||
}
|
}
|
||||||
type testCase[T int, K int, V int] struct {
|
type testCase[T int, K int, V int] struct {
|
||||||
name string
|
name string
|
||||||
args args[T, K, V]
|
args args[T, K, V]
|
||||||
wantR SimpleMapStream[K, V]
|
wantR MapStream[K, V]
|
||||||
}
|
}
|
||||||
tests := []testCase[int, int, int]{
|
tests := []testCase[int, int, int]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args[int, int, int]{
|
args: args[int, int, int]{
|
||||||
a: NewSimpleSliceStream(number.Range(1, 10, 1)),
|
a: NewStream(number.Range(1, 10, 1)),
|
||||||
fn: func(i int) (int, int, bool) {
|
fn: func(i int) (int, int, bool) {
|
||||||
if i > 6 {
|
if i > 6 {
|
||||||
return i, i, true
|
return i, i, true
|
||||||
|
@ -592,8 +592,8 @@ func TestSimpleSliceFilterAndMapToMap(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if gotR := SimpleSliceFilterAndMapToMap(tt.args.a, tt.args.fn, tt.args.isCoverPrev); !reflect.DeepEqual(gotR, tt.wantR) {
|
if gotR := SliceFilterAndMapToMapStream(tt.args.a, tt.args.fn, tt.args.isCoverPrev); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
t.Errorf("SimpleSliceFilterAndMapToMap() = %v, want %v", gotR, tt.wantR)
|
t.Errorf("SliceFilterAndMapToMapStream() = %v, want %v", gotR, tt.wantR)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user