helper函数 分层
This commit is contained in:
parent
2188619755
commit
04858e304f
|
@ -1,31 +1,14 @@
|
||||||
package helper
|
package helper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type IntNumber interface {
|
|
||||||
~int | ~int64 | ~int32 | ~int8 | ~int16 |
|
|
||||||
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func ToAny[T any](v T) any {
|
func ToAny[T any](v T) any {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsContainInArr[T comparable](a T, arr []T) bool {
|
func StructColumnToSlice[T any, M any](arr []M, field string) (r []T) {
|
||||||
for _, v := range arr {
|
|
||||||
if a == v {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func StructColumn[T any, M any](arr []M, field string) (r []T) {
|
|
||||||
for i := 0; i < len(arr); i++ {
|
for i := 0; i < len(arr); i++ {
|
||||||
v := reflect.ValueOf(arr[i]).FieldByName(field).Interface()
|
v := reflect.ValueOf(arr[i]).FieldByName(field).Interface()
|
||||||
if val, ok := v.(T); ok {
|
if val, ok := v.(T); ok {
|
||||||
|
@ -34,79 +17,3 @@ func StructColumn[T any, M any](arr []M, field string) (r []T) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func RandNum[T IntNumber](start, end T) T {
|
|
||||||
end++
|
|
||||||
return T(rand.Int63n(int64(end-start))) + start
|
|
||||||
}
|
|
||||||
|
|
||||||
type anyArr[T any] struct {
|
|
||||||
data []T
|
|
||||||
fn func(i, j T) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r anyArr[T]) Len() int {
|
|
||||||
return len(r.data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r anyArr[T]) Swap(i, j int) {
|
|
||||||
r.data[i], r.data[j] = r.data[j], r.data[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r anyArr[T]) Less(i, j int) bool {
|
|
||||||
return r.fn(r.data[i], r.data[j])
|
|
||||||
}
|
|
||||||
|
|
||||||
func SimpleSort[T any](arr []T, fn func(i, j T) bool) {
|
|
||||||
slice := anyArr[T]{
|
|
||||||
data: arr,
|
|
||||||
fn: fn,
|
|
||||||
}
|
|
||||||
sort.Sort(slice)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func SimpleSortR[T any](arr []T, fn func(i, j T) bool) (r []T) {
|
|
||||||
r = make([]T, 0, len(arr))
|
|
||||||
for _, t := range arr {
|
|
||||||
r = append(r, t)
|
|
||||||
}
|
|
||||||
slice := anyArr[T]{
|
|
||||||
data: r,
|
|
||||||
fn: fn,
|
|
||||||
}
|
|
||||||
sort.Sort(slice)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func Min[T IntNumber | ~float64 | ~float32](a ...T) T {
|
|
||||||
min := a[0]
|
|
||||||
for _, t := range a {
|
|
||||||
if min > t {
|
|
||||||
min = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return min
|
|
||||||
}
|
|
||||||
|
|
||||||
func Max[T IntNumber | ~float64 | ~float32](a ...T) T {
|
|
||||||
max := a[0]
|
|
||||||
for _, t := range a {
|
|
||||||
if max < t {
|
|
||||||
max = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return max
|
|
||||||
}
|
|
||||||
|
|
||||||
func Sum[T IntNumber | ~float64 | ~float32](a ...T) T {
|
|
||||||
s := T(0)
|
|
||||||
for _, t := range a {
|
|
||||||
s += t
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func NumberToString[T IntNumber | ~float64 | ~float32](n T) string {
|
|
||||||
return fmt.Sprintf("%v", n)
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,17 +34,17 @@ func BenchmarkOr(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkStructColumn(b *testing.B) {
|
func BenchmarkStructColumnToSlice(b *testing.B) {
|
||||||
y := getX()
|
y := getX()
|
||||||
fmt.Println(y)
|
fmt.Println(y)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
//b.N = 2
|
//b.N = 2
|
||||||
for i := 0; i < 1; i++ {
|
for i := 0; i < 1; i++ {
|
||||||
StructColumn[int, *x](y, "Id")
|
StructColumnToSlice[int, *x](y, "Id")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStructColumn(t *testing.T) {
|
func TestStructColumnToSlice(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
arr []x
|
arr []x
|
||||||
field string
|
field string
|
||||||
|
@ -67,14 +67,14 @@ func TestStructColumn(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 := StructColumn[uint64, x](tt.args.arr, tt.args.field); !reflect.DeepEqual(gotR, tt.wantR) {
|
if gotR := StructColumnToSlice[uint64, x](tt.args.arr, tt.args.field); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
t.Errorf("StructColumn() = %v, want %v", gotR, tt.wantR)
|
t.Errorf("StructColumnToSlice() = %v, want %v", gotR, tt.wantR)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestToInterface(t *testing.T) {
|
func TestToAny(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
v int
|
v int
|
||||||
}
|
}
|
||||||
|
@ -97,239 +97,3 @@ func TestToInterface(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRandNum(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
start int
|
|
||||||
end int
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "t1",
|
|
||||||
args: args{
|
|
||||||
start: 1,
|
|
||||||
end: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
for i := 0; i < 100; i++ {
|
|
||||||
got := RandNum(tt.args.start, tt.args.end)
|
|
||||||
if got > tt.args.end || got < tt.args.start {
|
|
||||||
t.Errorf("RandNum() = %v, range error", got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSimpleSort(t *testing.T) {
|
|
||||||
type xy struct {
|
|
||||||
x int
|
|
||||||
y int
|
|
||||||
}
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
arr []xy
|
|
||||||
fn func(i, j xy) bool
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
wantR []xy
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "t1",
|
|
||||||
args: args{
|
|
||||||
arr: []xy{
|
|
||||||
{1, 2},
|
|
||||||
{3, 4},
|
|
||||||
{1, 3},
|
|
||||||
{2, 1},
|
|
||||||
{1, 6},
|
|
||||||
},
|
|
||||||
fn: func(i, j xy) bool {
|
|
||||||
if i.x < j.x {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if i.x == j.x && i.y > i.y {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantR: []xy{
|
|
||||||
{1, 2},
|
|
||||||
{1, 3},
|
|
||||||
{1, 6},
|
|
||||||
{2, 1},
|
|
||||||
{3, 4},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if SimpleSort(tt.args.arr, tt.args.fn); !reflect.DeepEqual(tt.args.arr, tt.wantR) {
|
|
||||||
t.Errorf("SimpleSort() = %v, want %v", tt.args.arr, tt.wantR)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMin(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
a []int
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
want int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "t1",
|
|
||||||
args: args{a: []int{1, 2, 3}},
|
|
||||||
want: 1,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := Min(tt.args.a...); got != tt.want {
|
|
||||||
t.Errorf("Min() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMax(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
a []int
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
want int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "t1",
|
|
||||||
args: args{a: []int{1, 2, 3}},
|
|
||||||
want: 3,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := Max(tt.args.a...); got != tt.want {
|
|
||||||
t.Errorf("Max() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSum(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
a []int
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
want int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "t1",
|
|
||||||
args: args{a: RangeSlice(1, 10, 1)},
|
|
||||||
want: 55,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := Sum(tt.args.a...); got != tt.want {
|
|
||||||
t.Errorf("Sum() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNumberToString(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
n float64
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
want string
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "t1",
|
|
||||||
args: args{n: 111},
|
|
||||||
want: "111",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "t2",
|
|
||||||
args: args{n: 111.222222},
|
|
||||||
want: "111.222222",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := NumberToString(tt.args.n); got != tt.want {
|
|
||||||
t.Errorf("NumberToString() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSimpleSortR(t *testing.T) {
|
|
||||||
type xy struct {
|
|
||||||
x int
|
|
||||||
y int
|
|
||||||
}
|
|
||||||
type args[T any] struct {
|
|
||||||
arr []T
|
|
||||||
fn func(i, j T) bool
|
|
||||||
}
|
|
||||||
type testCase[T any] struct {
|
|
||||||
name string
|
|
||||||
args args[T]
|
|
||||||
wantR []T
|
|
||||||
}
|
|
||||||
tests := []testCase[xy]{
|
|
||||||
{
|
|
||||||
name: "t1",
|
|
||||||
args: args[xy]{
|
|
||||||
arr: []xy{
|
|
||||||
{1, 2},
|
|
||||||
{3, 4},
|
|
||||||
{1, 3},
|
|
||||||
{2, 1},
|
|
||||||
{1, 6},
|
|
||||||
},
|
|
||||||
fn: func(i, j xy) bool {
|
|
||||||
if i.x < j.x {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if i.x == j.x && i.y > i.y {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
},
|
|
||||||
wantR: []xy{
|
|
||||||
{1, 2},
|
|
||||||
{1, 3},
|
|
||||||
{1, 6},
|
|
||||||
{2, 1},
|
|
||||||
{3, 4},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if gotR := SimpleSortR[xy](tt.args.arr, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
|
|
||||||
t.Errorf("SimpleSortR() = %v, want %v", gotR, tt.wantR)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package helper
|
package html
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/dlclark/regexp2"
|
"github.com/dlclark/regexp2"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -119,7 +120,7 @@ func StripTagsX(str, allowable string) string {
|
||||||
var tagx = regexp.MustCompile(`(</?[a-z0-9]+?)( |>)`)
|
var tagx = regexp.MustCompile(`(</?[a-z0-9]+?)( |>)`)
|
||||||
var selfCloseTags = map[string]string{"area": "", "base": "", "basefont": "", "br": "", "col": "", "command": "", "embed": "", "frame": "", "hr": "", "img": "", "input": "", "isindex": "", "link": "", "meta": "", "param": "", "source": "", "track": "", "wbr": ""}
|
var selfCloseTags = map[string]string{"area": "", "base": "", "basefont": "", "br": "", "col": "", "command": "", "embed": "", "frame": "", "hr": "", "img": "", "input": "", "isindex": "", "link": "", "meta": "", "param": "", "source": "", "track": "", "wbr": ""}
|
||||||
|
|
||||||
func CloseHtmlTag(str string) string {
|
func CloseTag(str string) string {
|
||||||
tags := tag.FindAllString(str, -1)
|
tags := tag.FindAllString(str, -1)
|
||||||
if len(tags) < 1 {
|
if len(tags) < 1 {
|
||||||
return str
|
return str
|
||||||
|
@ -135,13 +136,13 @@ func CloseHtmlTag(str string) string {
|
||||||
}
|
}
|
||||||
tagss = append(tagss, ss)
|
tagss = append(tagss, ss)
|
||||||
}
|
}
|
||||||
r := SliceMap(SliceReverse(ClearClosedTag(tagss)), func(s string) string {
|
r := slice.Map(slice.Reverse(UnClosedTag(tagss)), func(s string) string {
|
||||||
return fmt.Sprintf("</%s>", strings.Trim(s, "<>"))
|
return fmt.Sprintf("</%s>", strings.Trim(s, "<>"))
|
||||||
})
|
})
|
||||||
return strings.Join(r, "")
|
return strings.Join(r, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func ClearClosedTag(s []string) []string {
|
func UnClosedTag(s []string) []string {
|
||||||
i := 0
|
i := 0
|
||||||
for {
|
for {
|
||||||
if len(s[i:]) < 2 {
|
if len(s[i:]) < 2 {
|
|
@ -1,4 +1,4 @@
|
||||||
package helper
|
package html
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -183,8 +183,8 @@ func TestCloseHtmlTag(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 got := CloseHtmlTag(tt.args.str); !reflect.DeepEqual(got, tt.want) {
|
if got := CloseTag(tt.args.str); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("CloseHtmlTag() = %v, want %v", got, tt.want)
|
t.Errorf("CloseTag() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -222,8 +222,8 @@ func Test_clearTag(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 got := ClearClosedTag(tt.args.s); !reflect.DeepEqual(got, tt.want) {
|
if got := UnClosedTag(tt.args.s); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("ClearClosedTag() = %v, want %v", got, tt.want)
|
t.Errorf("UnClosedTag() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package helper
|
package maps
|
||||||
|
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
|
@ -25,14 +25,14 @@ func GetStrMapAnyVal[T any](key string, v map[string]any) (r T, o bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetStrMapAnyValToAny(key string, v map[string]any) (r any, o bool) {
|
func GetStrMapAnyValWithAny(key string, v map[string]any) (r any, o bool) {
|
||||||
k := strings.Split(key, ".")
|
k := strings.Split(key, ".")
|
||||||
if len(k) > 1 {
|
if len(k) > 1 {
|
||||||
val, ok := v[k[0]]
|
val, ok := v[k[0]]
|
||||||
if ok {
|
if ok {
|
||||||
vx, ok := val.(map[string]any)
|
vx, ok := val.(map[string]any)
|
||||||
if ok {
|
if ok {
|
||||||
r, o = GetStrMapAnyValToAny(strings.Join(k[1:], "."), vx)
|
r, o = GetStrMapAnyValWithAny(strings.Join(k[1:], "."), vx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
|
@ -1,4 +1,4 @@
|
||||||
package helper
|
package maps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -65,7 +65,7 @@ func TestGetStrMapAnyVal(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetStrMapAnyValToAny(t *testing.T) {
|
func TestGetStrMapAnyValWithAny(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
key string
|
key string
|
||||||
v map[string]any
|
v map[string]any
|
||||||
|
@ -113,12 +113,12 @@ func TestGetStrMapAnyValToAny(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) {
|
||||||
gotR, gotO := GetStrMapAnyValToAny(tt.args.key, tt.args.v)
|
gotR, gotO := GetStrMapAnyValWithAny(tt.args.key, tt.args.v)
|
||||||
if !reflect.DeepEqual(gotR, tt.wantR) {
|
if !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
t.Errorf("GetStrMapAnyValToAny() gotR = %v, want %v", gotR, tt.wantR)
|
t.Errorf("GetStrMapAnyValWithAny() gotR = %v, want %v", gotR, tt.wantR)
|
||||||
}
|
}
|
||||||
if gotO != tt.wantO {
|
if gotO != tt.wantO {
|
||||||
t.Errorf("GetStrMapAnyValToAny() gotO = %v, want %v", gotO, tt.wantO)
|
t.Errorf("GetStrMapAnyValWithAny() gotO = %v, want %v", gotO, tt.wantO)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package helper
|
package maps
|
||||||
|
|
||||||
import "encoding/json"
|
import "encoding/json"
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ func StructToAnyMap[K comparable, T any](s T) (r map[K]any, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func MapToSlice[T any, K comparable, V any](m map[K]V, fn func(K, V) (T, bool)) (r []T) {
|
func FilterToSlice[T any, K comparable, V any](m map[K]V, fn func(K, V) (T, bool)) (r []T) {
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
vv, ok := fn(k, v)
|
vv, ok := fn(k, v)
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -31,15 +31,15 @@ func MapToSlice[T any, K comparable, V any](m map[K]V, fn func(K, V) (T, bool))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapAnyAnyToStrAny map[any]any => map[string]any 方便json转换
|
// AnyAnyToStrAny map[any]any => map[string]any 方便json转换
|
||||||
func MapAnyAnyToStrAny(m map[any]any) (r map[string]any) {
|
func AnyAnyToStrAny(m map[any]any) (r map[string]any) {
|
||||||
r = make(map[string]any)
|
r = make(map[string]any)
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
kk, ok := k.(string)
|
kk, ok := k.(string)
|
||||||
if ok {
|
if ok {
|
||||||
vv, ok := v.(map[any]any)
|
vv, ok := v.(map[any]any)
|
||||||
if ok {
|
if ok {
|
||||||
r[kk] = MapAnyAnyToStrAny(vv)
|
r[kk] = AnyAnyToStrAny(vv)
|
||||||
} else {
|
} else {
|
||||||
r[kk] = v
|
r[kk] = v
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package helper
|
package maps
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -118,7 +118,15 @@ func TestStructToAnyMap(t *testing.T) {
|
||||||
t.Errorf("StructToAnyMap() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("StructToAnyMap() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(gotR, tt.wantR) {
|
gr, err := StrAnyMapToStruct[Me](gotR)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
wr, err := StrAnyMapToStruct[Me](tt.wantR)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(gr, wr) {
|
||||||
t.Errorf("StructToAnyMap() gotR = %v, want %v", gotR, tt.wantR)
|
t.Errorf("StructToAnyMap() gotR = %v, want %v", gotR, tt.wantR)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -157,8 +165,8 @@ func TestMapToSlice(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 := MapToSlice(tt.args.m, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
|
if gotR := FilterToSlice(tt.args.m, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
t.Errorf("MapToSlice() = %v, want %v", gotR, tt.wantR)
|
t.Errorf("FilterToSlice() = %v, want %v", gotR, tt.wantR)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
67
helper/number/number.go
Normal file
67
helper/number/number.go
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
package number
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IntNumber interface {
|
||||||
|
~int | ~int64 | ~int32 | ~int8 | ~int16 |
|
||||||
|
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func Range[T IntNumber](start, end, step T) []T {
|
||||||
|
if step == 0 {
|
||||||
|
panic("step can't be 0")
|
||||||
|
}
|
||||||
|
l := int((end-start+1)/step + 1)
|
||||||
|
if l < 0 {
|
||||||
|
l = 0 - l
|
||||||
|
}
|
||||||
|
r := make([]T, 0, l)
|
||||||
|
for i := start; ; {
|
||||||
|
r = append(r, i)
|
||||||
|
i = i + step
|
||||||
|
if (step > 0 && i > end) || (step < 0 && i < end) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
min := a[0]
|
||||||
|
for _, t := range a {
|
||||||
|
if min > t {
|
||||||
|
min = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
|
||||||
|
func Max[T IntNumber | ~float64 | ~float32](a ...T) T {
|
||||||
|
max := a[0]
|
||||||
|
for _, t := range a {
|
||||||
|
if max < t {
|
||||||
|
max = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return max
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sum[T IntNumber | ~float64 | ~float32](a ...T) T {
|
||||||
|
s := T(0)
|
||||||
|
for _, t := range a {
|
||||||
|
s += t
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToString[T IntNumber | ~float64 | ~float32](n T) string {
|
||||||
|
return fmt.Sprintf("%v", n)
|
||||||
|
}
|
193
helper/number/number_test.go
Normal file
193
helper/number/number_test.go
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
package number
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRange(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
start int
|
||||||
|
end int
|
||||||
|
step int
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want []int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args{
|
||||||
|
start: 1,
|
||||||
|
end: 5,
|
||||||
|
step: 1,
|
||||||
|
},
|
||||||
|
want: []int{1, 2, 3, 4, 5},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "t2",
|
||||||
|
args: args{
|
||||||
|
start: 0,
|
||||||
|
end: 5,
|
||||||
|
step: 2,
|
||||||
|
},
|
||||||
|
want: []int{0, 2, 4},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "t3",
|
||||||
|
args: args{
|
||||||
|
start: 1,
|
||||||
|
end: 11,
|
||||||
|
step: 3,
|
||||||
|
},
|
||||||
|
want: []int{1, 4, 7, 10},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "t4",
|
||||||
|
args: args{
|
||||||
|
start: 0,
|
||||||
|
end: -5,
|
||||||
|
step: -1,
|
||||||
|
},
|
||||||
|
want: []int{0, -1, -2, -3, -4, -5},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := Range(tt.args.start, tt.args.end, tt.args.step); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("Range() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMin(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
a []int
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args{a: []int{1, 2, 3}},
|
||||||
|
want: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := Min(tt.args.a...); got != tt.want {
|
||||||
|
t.Errorf("Min() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMax(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
a []int
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args{a: []int{1, 2, 3}},
|
||||||
|
want: 3,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := Max(tt.args.a...); got != tt.want {
|
||||||
|
t.Errorf("Max() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSum(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
a []int
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args{a: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}},
|
||||||
|
want: 55,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := Sum(tt.args.a...); got != tt.want {
|
||||||
|
t.Errorf("Sum() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToString(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
n float64
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args{n: 111},
|
||||||
|
want: "111",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "t2",
|
||||||
|
args: args{n: 111.222222},
|
||||||
|
want: "111.222222",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := ToString(tt.args.n); got != tt.want {
|
||||||
|
t.Errorf("NumberToString() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRand(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
start int
|
||||||
|
end int
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args{
|
||||||
|
start: 1,
|
||||||
|
end: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
got := Rand(tt.args.start, tt.args.end)
|
||||||
|
if got > tt.args.end || got < tt.args.start {
|
||||||
|
t.Errorf("RandNum() = %v, range error", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package helper
|
package slice
|
||||||
|
|
||||||
func SliceMap[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))
|
||||||
for _, t := range arr {
|
for _, t := range arr {
|
||||||
r = append(r, fn(t))
|
r = append(r, fn(t))
|
||||||
|
@ -8,7 +8,7 @@ func SliceMap[T, R any](arr []T, fn func(T) R) []R {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func SliceFilterAndMap[N any, T any](arr []T, fn func(T) (N, bool)) (r []N) {
|
func FilterAndMap[N any, T any](arr []T, fn func(T) (N, bool)) (r []N) {
|
||||||
for _, t := range arr {
|
for _, t := range arr {
|
||||||
x, ok := fn(t)
|
x, ok := fn(t)
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -18,7 +18,7 @@ func SliceFilterAndMap[N any, T any](arr []T, fn func(T) (N, bool)) (r []N) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func SliceFilter[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 {
|
||||||
if fn(t) {
|
if fn(t) {
|
||||||
|
@ -28,14 +28,14 @@ func SliceFilter[T any](arr []T, fn func(T) bool) []T {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func SliceReduce[R, T any](arr []T, fn func(T, R) R, r R) R {
|
func Reduce[R, T any](arr []T, fn func(T, R) R, r R) R {
|
||||||
for _, t := range arr {
|
for _, t := range arr {
|
||||||
r = fn(t, r)
|
r = fn(t, r)
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func SliceReverse[T any](arr []T) []T {
|
func Reverse[T any](arr []T) []T {
|
||||||
var r = make([]T, 0, len(arr))
|
var r = make([]T, 0, len(arr))
|
||||||
for i := len(arr); i > 0; i-- {
|
for i := len(arr); i > 0; i-- {
|
||||||
r = append(r, arr[i-1])
|
r = append(r, arr[i-1])
|
||||||
|
@ -43,7 +43,7 @@ func SliceReverse[T any](arr []T) []T {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func SliceSelfReverse[T any](arr []T) []T {
|
func ReverseSelf[T any](arr []T) []T {
|
||||||
l := len(arr)
|
l := len(arr)
|
||||||
half := l / 2
|
half := l / 2
|
||||||
for i := 0; i < half; i++ {
|
for i := 0; i < half; i++ {
|
||||||
|
@ -52,13 +52,13 @@ func SliceSelfReverse[T any](arr []T) []T {
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
func SimpleSliceToMap[K comparable, V any](arr []V, fn func(V) K) map[K]V {
|
func SimpleToMap[K comparable, V any](arr []V, fn func(V) K) map[K]V {
|
||||||
return SliceToMap(arr, func(v V) (K, V) {
|
return ToMap(arr, func(v V) (K, V) {
|
||||||
return fn(v), v
|
return fn(v), v
|
||||||
}, true)
|
}, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SliceToMap[K comparable, V, T any](arr []V, fn func(V) (K, T), isCoverPrev bool) map[K]T {
|
func ToMap[K comparable, V, T any](arr []V, fn func(V) (K, T), isCoverPrev bool) map[K]T {
|
||||||
m := make(map[K]T)
|
m := make(map[K]T)
|
||||||
for _, v := range arr {
|
for _, v := range arr {
|
||||||
k, r := fn(v)
|
k, r := fn(v)
|
||||||
|
@ -72,26 +72,7 @@ func SliceToMap[K comparable, V, T any](arr []V, fn func(V) (K, T), isCoverPrev
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func RangeSlice[T IntNumber](start, end, step T) []T {
|
func Pagination[T any](arr []T, page, pageSize int) []T {
|
||||||
if step == 0 {
|
|
||||||
panic("step can't be 0")
|
|
||||||
}
|
|
||||||
l := int((end-start+1)/step + 1)
|
|
||||||
if l < 0 {
|
|
||||||
l = 0 - l
|
|
||||||
}
|
|
||||||
r := make([]T, 0, l)
|
|
||||||
for i := start; ; {
|
|
||||||
r = append(r, i)
|
|
||||||
i = i + step
|
|
||||||
if (step > 0 && i > end) || (step < 0 && i < end) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func SlicePagination[T any](arr []T, page, pageSize int) []T {
|
|
||||||
start := (page - 1) * pageSize
|
start := (page - 1) * pageSize
|
||||||
l := len(arr)
|
l := len(arr)
|
||||||
if start > l {
|
if start > l {
|
||||||
|
@ -104,7 +85,7 @@ func SlicePagination[T any](arr []T, page, pageSize int) []T {
|
||||||
return arr[start:end]
|
return arr[start:end]
|
||||||
}
|
}
|
||||||
|
|
||||||
func SliceChunk[T any](arr []T, size int) [][]T {
|
func Chunk[T any](arr []T, size int) [][]T {
|
||||||
var r [][]T
|
var r [][]T
|
||||||
i := 0
|
i := 0
|
||||||
for {
|
for {
|
||||||
|
@ -153,3 +134,13 @@ func Comb[T any](arr []T, m int) (r [][]T) {
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func IsContained[T comparable](a T, arr []T) bool {
|
||||||
|
for _, v := range arr {
|
||||||
|
if a == v {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -1,12 +1,13 @@
|
||||||
package helper
|
package slice
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSlicePagination(t *testing.T) {
|
func TestPagination(t *testing.T) {
|
||||||
arr := RangeSlice[int](1, 10, 1)
|
arr := number.Range[int](1, 10, 1)
|
||||||
type args struct {
|
type args struct {
|
||||||
arr []int
|
arr []int
|
||||||
page int
|
page int
|
||||||
|
@ -24,7 +25,7 @@ func TestSlicePagination(t *testing.T) {
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 2,
|
pageSize: 2,
|
||||||
},
|
},
|
||||||
want: RangeSlice[int](1, 2, 1),
|
want: number.Range[int](1, 2, 1),
|
||||||
}, {
|
}, {
|
||||||
name: "t2",
|
name: "t2",
|
||||||
args: args{
|
args: args{
|
||||||
|
@ -32,7 +33,7 @@ func TestSlicePagination(t *testing.T) {
|
||||||
page: 2,
|
page: 2,
|
||||||
pageSize: 2,
|
pageSize: 2,
|
||||||
},
|
},
|
||||||
want: RangeSlice[int](3, 4, 1),
|
want: number.Range[int](3, 4, 1),
|
||||||
}, {
|
}, {
|
||||||
name: "t3",
|
name: "t3",
|
||||||
args: args{
|
args: args{
|
||||||
|
@ -53,14 +54,14 @@ func TestSlicePagination(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 got := SlicePagination(tt.args.arr, tt.args.page, tt.args.pageSize); !reflect.DeepEqual(got, tt.want) {
|
if got := Pagination(tt.args.arr, tt.args.page, tt.args.pageSize); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SlicePagination() = %v, want %v", got, tt.want)
|
t.Errorf("Pagination() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceReduce(t *testing.T) {
|
func TestReduce(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
arr []int
|
arr []int
|
||||||
fn func(int, int) int
|
fn func(int, int) int
|
||||||
|
@ -73,7 +74,7 @@ func TestSliceReduce(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args{arr: RangeSlice(1, 10, 1), fn: func(i int, i2 int) int {
|
args: args{arr: number.Range(1, 10, 1), fn: func(i int, i2 int) int {
|
||||||
return i + i2
|
return i + i2
|
||||||
}},
|
}},
|
||||||
want: 55,
|
want: 55,
|
||||||
|
@ -81,14 +82,14 @@ func TestSliceReduce(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 got := SliceReduce(tt.args.arr, tt.args.fn, tt.args.r); !reflect.DeepEqual(got, tt.want) {
|
if got := Reduce(tt.args.arr, tt.args.fn, tt.args.r); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SliceReduce() = %v, want %v", got, tt.want)
|
t.Errorf("Reduce() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceFilter(t *testing.T) {
|
func TestFilter(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
arr []int
|
arr []int
|
||||||
fn func(int) bool
|
fn func(int) bool
|
||||||
|
@ -100,22 +101,22 @@ func TestSliceFilter(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args{arr: RangeSlice(1, 10, 1), fn: func(i int) bool {
|
args: args{arr: number.Range(1, 10, 1), fn: func(i int) bool {
|
||||||
return i > 4
|
return i > 4
|
||||||
}},
|
}},
|
||||||
want: RangeSlice(5, 10, 1),
|
want: number.Range(5, 10, 1),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
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 := SliceFilter(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
if got := Filter(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SliceFilter() = %v, want %v", got, tt.want)
|
t.Errorf("Filter() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceMap(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
arr []int8
|
arr []int8
|
||||||
fn func(int8) int
|
fn func(int8) int
|
||||||
|
@ -128,24 +129,24 @@ func TestSliceMap(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args{
|
args: args{
|
||||||
arr: RangeSlice[int8](1, 10, 1),
|
arr: number.Range[int8](1, 10, 1),
|
||||||
fn: func(i int8) int {
|
fn: func(i int8) int {
|
||||||
return int(i)
|
return int(i)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: RangeSlice(1, 10, 1),
|
want: number.Range(1, 10, 1),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
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 := SliceMap(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
if got := Map(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SliceMap() = %v, want %v", got, tt.want)
|
t.Errorf("Map() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceReverse(t *testing.T) {
|
func TestReverse(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
arr []int
|
arr []int
|
||||||
}
|
}
|
||||||
|
@ -156,71 +157,14 @@ func TestSliceReverse(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args{arr: RangeSlice(1, 10, 1)},
|
args: args{arr: number.Range(1, 10, 1)},
|
||||||
want: RangeSlice(10, 1, -1),
|
want: number.Range(10, 1, -1),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
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 := SliceReverse(tt.args.arr); !reflect.DeepEqual(got, tt.want) {
|
if got := Reverse(tt.args.arr); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SliceReverse() = %v, want %v", got, tt.want)
|
t.Errorf("Reverse() = %v, want %v", got, tt.want)
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRangeSlice(t *testing.T) {
|
|
||||||
type args struct {
|
|
||||||
start int
|
|
||||||
end int
|
|
||||||
step int
|
|
||||||
}
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
args args
|
|
||||||
want []int
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "t1",
|
|
||||||
args: args{
|
|
||||||
start: 1,
|
|
||||||
end: 5,
|
|
||||||
step: 1,
|
|
||||||
},
|
|
||||||
want: []int{1, 2, 3, 4, 5},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "t2",
|
|
||||||
args: args{
|
|
||||||
start: 0,
|
|
||||||
end: 5,
|
|
||||||
step: 2,
|
|
||||||
},
|
|
||||||
want: []int{0, 2, 4},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "t3",
|
|
||||||
args: args{
|
|
||||||
start: 1,
|
|
||||||
end: 11,
|
|
||||||
step: 3,
|
|
||||||
},
|
|
||||||
want: []int{1, 4, 7, 10},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "t4",
|
|
||||||
args: args{
|
|
||||||
start: 0,
|
|
||||||
end: -5,
|
|
||||||
step: -1,
|
|
||||||
},
|
|
||||||
want: []int{0, -1, -2, -3, -4, -5},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := RangeSlice(tt.args.start, tt.args.end, tt.args.step); !reflect.DeepEqual(got, tt.want) {
|
|
||||||
t.Errorf("RangeSlice() = %v, want %v", got, tt.want)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -240,20 +184,20 @@ func TestSlice(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args{
|
args: args{
|
||||||
arr: RangeSlice(1, 10, 1),
|
arr: number.Range(1, 10, 1),
|
||||||
offset: 3,
|
offset: 3,
|
||||||
length: 2,
|
length: 2,
|
||||||
},
|
},
|
||||||
wantR: RangeSlice(4, 5, 1),
|
wantR: number.Range(4, 5, 1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "t2",
|
name: "t2",
|
||||||
args: args{
|
args: args{
|
||||||
arr: RangeSlice(1, 10, 1),
|
arr: number.Range(1, 10, 1),
|
||||||
offset: 3,
|
offset: 3,
|
||||||
length: 0,
|
length: 0,
|
||||||
},
|
},
|
||||||
wantR: RangeSlice(4, 10, 1),
|
wantR: number.Range(4, 10, 1),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -278,7 +222,7 @@ func TestComb(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args{
|
args: args{
|
||||||
arr: RangeSlice(1, 5, 1),
|
arr: number.Range(1, 5, 1),
|
||||||
m: 2,
|
m: 2,
|
||||||
},
|
},
|
||||||
wantR: [][]int{
|
wantR: [][]int{
|
||||||
|
@ -297,7 +241,7 @@ func TestComb(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t2",
|
name: "t2",
|
||||||
args: args{
|
args: args{
|
||||||
arr: RangeSlice(1, 5, 1),
|
arr: number.Range(1, 5, 1),
|
||||||
m: 3,
|
m: 3,
|
||||||
},
|
},
|
||||||
wantR: [][]int{
|
wantR: [][]int{
|
||||||
|
@ -316,7 +260,7 @@ func TestComb(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t3",
|
name: "t3",
|
||||||
args: args{
|
args: args{
|
||||||
arr: RangeSlice(1, 5, 1),
|
arr: number.Range(1, 5, 1),
|
||||||
m: 4,
|
m: 4,
|
||||||
},
|
},
|
||||||
wantR: [][]int{
|
wantR: [][]int{
|
||||||
|
@ -337,7 +281,7 @@ func TestComb(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceChunk(t *testing.T) {
|
func TestChunk(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
arr []int
|
arr []int
|
||||||
size int
|
size int
|
||||||
|
@ -350,7 +294,7 @@ func TestSliceChunk(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args{
|
args: args{
|
||||||
arr: RangeSlice(1, 7, 1),
|
arr: number.Range(1, 7, 1),
|
||||||
size: 2,
|
size: 2,
|
||||||
},
|
},
|
||||||
want: [][]int{{1, 2}, {3, 4}, {5, 6}, {7}},
|
want: [][]int{{1, 2}, {3, 4}, {5, 6}, {7}},
|
||||||
|
@ -358,7 +302,7 @@ func TestSliceChunk(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t2",
|
name: "t2",
|
||||||
args: args{
|
args: args{
|
||||||
arr: RangeSlice(1, 8, 1),
|
arr: number.Range(1, 8, 1),
|
||||||
size: 2,
|
size: 2,
|
||||||
},
|
},
|
||||||
want: [][]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}},
|
want: [][]int{{1, 2}, {3, 4}, {5, 6}, {7, 8}},
|
||||||
|
@ -366,8 +310,8 @@ func TestSliceChunk(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 got := SliceChunk(tt.args.arr, tt.args.size); !reflect.DeepEqual(got, tt.want) {
|
if got := Chunk(tt.args.arr, tt.args.size); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SliceChunk() = %v, want %v", got, tt.want)
|
t.Errorf("Chunk() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -393,14 +337,14 @@ func TestSimpleSliceToMap(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 got := SimpleSliceToMap(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
if got := SimpleToMap(tt.args.arr, tt.args.fn); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SimpleSliceToMap() = %v, want %v", got, tt.want)
|
t.Errorf("SimpleToMap() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceToMap(t *testing.T) {
|
func TestToMap(t *testing.T) {
|
||||||
type ss struct {
|
type ss struct {
|
||||||
id int
|
id int
|
||||||
v string
|
v string
|
||||||
|
@ -439,14 +383,14 @@ func TestSliceToMap(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 got := SliceToMap(tt.args.arr, tt.args.fn, tt.args.isCoverPrev); !reflect.DeepEqual(got, tt.want) {
|
if got := ToMap(tt.args.arr, tt.args.fn, tt.args.isCoverPrev); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SliceToMap() = %v, want %v", got, tt.want)
|
t.Errorf("ToMap() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceSelfReverse(t *testing.T) {
|
func TestReverseSelf(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
arr []int
|
arr []int
|
||||||
}
|
}
|
||||||
|
@ -458,27 +402,27 @@ func TestSliceSelfReverse(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args{
|
args: args{
|
||||||
arr: RangeSlice(1, 10, 1),
|
arr: number.Range(1, 10, 1),
|
||||||
},
|
},
|
||||||
want: RangeSlice(10, 1, -1),
|
want: number.Range(10, 1, -1),
|
||||||
}, {
|
}, {
|
||||||
name: "t2",
|
name: "t2",
|
||||||
args: args{
|
args: args{
|
||||||
arr: RangeSlice(1, 9, 1),
|
arr: number.Range(1, 9, 1),
|
||||||
},
|
},
|
||||||
want: RangeSlice(9, 1, -1),
|
want: number.Range(9, 1, -1),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
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 := SliceSelfReverse(tt.args.arr); !reflect.DeepEqual(got, tt.want) {
|
if got := ReverseSelf(tt.args.arr); !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("SliceSelfReverse() = %v, want %v", got, tt.want)
|
t.Errorf("ReverseSelf() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceFilterAndMap(t *testing.T) {
|
func TestFilterAndMap(t *testing.T) {
|
||||||
type a struct {
|
type a struct {
|
||||||
x int
|
x int
|
||||||
y string
|
y string
|
||||||
|
@ -513,8 +457,8 @@ func TestSliceFilterAndMap(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 := SliceFilterAndMap[string](tt.args.arr, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
|
if gotR := FilterAndMap[string](tt.args.arr, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
t.Errorf("SliceFilterAndMap() = %v, want %v", gotR, tt.wantR)
|
t.Errorf("FilterAndMap() = %v, want %v", gotR, tt.wantR)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
42
helper/slice/sort.go
Normal file
42
helper/slice/sort.go
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package slice
|
||||||
|
|
||||||
|
import "sort"
|
||||||
|
|
||||||
|
type anyArr[T any] struct {
|
||||||
|
data []T
|
||||||
|
fn func(i, j T) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r anyArr[T]) Len() int {
|
||||||
|
return len(r.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r anyArr[T]) Swap(i, j int) {
|
||||||
|
r.data[i], r.data[j] = r.data[j], r.data[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r anyArr[T]) Less(i, j int) bool {
|
||||||
|
return r.fn(r.data[i], r.data[j])
|
||||||
|
}
|
||||||
|
|
||||||
|
func SortSelf[T any](arr []T, fn func(i, j T) bool) {
|
||||||
|
slice := anyArr[T]{
|
||||||
|
data: arr,
|
||||||
|
fn: fn,
|
||||||
|
}
|
||||||
|
sort.Sort(slice)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sort[T any](arr []T, fn func(i, j T) bool) (r []T) {
|
||||||
|
r = make([]T, 0, len(arr))
|
||||||
|
for _, t := range arr {
|
||||||
|
r = append(r, t)
|
||||||
|
}
|
||||||
|
slice := anyArr[T]{
|
||||||
|
data: r,
|
||||||
|
fn: fn,
|
||||||
|
}
|
||||||
|
sort.Sort(slice)
|
||||||
|
return
|
||||||
|
}
|
112
helper/slice/sort_test.go
Normal file
112
helper/slice/sort_test.go
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
package slice
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSortSelf(t *testing.T) {
|
||||||
|
type xy struct {
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
}
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
arr []xy
|
||||||
|
fn func(i, j xy) bool
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantR []xy
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args{
|
||||||
|
arr: []xy{
|
||||||
|
{1, 2},
|
||||||
|
{3, 4},
|
||||||
|
{1, 3},
|
||||||
|
{2, 1},
|
||||||
|
{1, 6},
|
||||||
|
},
|
||||||
|
fn: func(i, j xy) bool {
|
||||||
|
if i.x < j.x {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if i.x == j.x && i.y > i.y {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantR: []xy{
|
||||||
|
{1, 2},
|
||||||
|
{1, 3},
|
||||||
|
{1, 6},
|
||||||
|
{2, 1},
|
||||||
|
{3, 4},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if SortSelf(tt.args.arr, tt.args.fn); !reflect.DeepEqual(tt.args.arr, tt.wantR) {
|
||||||
|
t.Errorf("SimpleSort() = %v, want %v", tt.args.arr, tt.wantR)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSort(t *testing.T) {
|
||||||
|
type xy struct {
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
}
|
||||||
|
type args[T any] struct {
|
||||||
|
arr []T
|
||||||
|
fn func(i, j T) bool
|
||||||
|
}
|
||||||
|
type testCase[T any] struct {
|
||||||
|
name string
|
||||||
|
args args[T]
|
||||||
|
wantR []T
|
||||||
|
}
|
||||||
|
tests := []testCase[xy]{
|
||||||
|
{
|
||||||
|
name: "t1",
|
||||||
|
args: args[xy]{
|
||||||
|
arr: []xy{
|
||||||
|
{1, 2},
|
||||||
|
{3, 4},
|
||||||
|
{1, 3},
|
||||||
|
{2, 1},
|
||||||
|
{1, 6},
|
||||||
|
},
|
||||||
|
fn: func(i, j xy) bool {
|
||||||
|
if i.x < j.x {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if i.x == j.x && i.y > i.y {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantR: []xy{
|
||||||
|
{1, 2},
|
||||||
|
{1, 3},
|
||||||
|
{1, 6},
|
||||||
|
{2, 1},
|
||||||
|
{3, 4},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if gotR := Sort[xy](tt.args.arr, tt.args.fn); !reflect.DeepEqual(gotR, tt.wantR) {
|
||||||
|
t.Errorf("SimpleSortR() = %v, want %v", gotR, tt.wantR)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package helper
|
package strings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
@ -7,7 +7,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func StrJoin(s ...string) (str string) {
|
func Join(s ...string) (str string) {
|
||||||
if len(s) == 1 {
|
if len(s) == 1 {
|
||||||
return s[0]
|
return s[0]
|
||||||
} else if len(s) > 1 {
|
} else if len(s) > 1 {
|
||||||
|
@ -20,7 +20,7 @@ func StrJoin(s ...string) (str string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func StringMd5(str string) string {
|
func Md5(str string) string {
|
||||||
h := md5.New()
|
h := md5.New()
|
||||||
_, err := io.WriteString(h, str)
|
_, err := io.WriteString(h, str)
|
||||||
if err != nil {
|
if err != nil {
|
|
@ -1,4 +1,4 @@
|
||||||
package helper
|
package strings
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@ func TestStrJoin(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 gotStr := StrJoin(tt.args.s...); gotStr != tt.wantStr {
|
if gotStr := Join(tt.args.s...); gotStr != tt.wantStr {
|
||||||
t.Errorf("StrJoin() = %v, want %v", gotStr, tt.wantStr)
|
t.Errorf("Join() = %v, want %v", gotStr, tt.wantStr)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/fthvgb1/wp-go/internal/mail"
|
"github.com/fthvgb1/wp-go/internal/mail"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/config"
|
"github.com/fthvgb1/wp-go/internal/pkg/config"
|
||||||
|
@ -81,7 +81,7 @@ func PostComment(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
newReq.Host = home.Host
|
newReq.Host = home.Host
|
||||||
newReq.Header.Set("Cookie", strings.Join(helper.SliceMap(c.Request.Cookies(), func(t *http.Cookie) string {
|
newReq.Header.Set("Cookie", strings.Join(slice.Map(c.Request.Cookies(), func(t *http.Cookie) string {
|
||||||
return fmt.Sprintf("%s=%s", t.Name, t.Value)
|
return fmt.Sprintf("%s=%s", t.Name, t.Value)
|
||||||
}), "; "))
|
}), "; "))
|
||||||
ress, er := http.DefaultClient.Do(newReq)
|
ress, er := http.DefaultClient.Do(newReq)
|
||||||
|
|
|
@ -2,7 +2,7 @@ package actions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||||
|
@ -49,7 +49,7 @@ func Detail(c *gin.Context) {
|
||||||
if isApproveComment == true {
|
if isApproveComment == true {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.HTML(status, helper.StrJoin(theme.GetTemplateName(), "/posts/detail.gohtml"), h)
|
c.HTML(status, str.Join(theme.GetTemplateName(), "/posts/detail.gohtml"), h)
|
||||||
}()
|
}()
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
Id := 0
|
Id := 0
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package actions
|
package actions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -11,7 +11,7 @@ import (
|
||||||
var tmp = "Mon, 02 Jan 2006 15:04:05 GMT"
|
var tmp = "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||||
|
|
||||||
func isCacheExpired(c *gin.Context, lastTime time.Time) bool {
|
func isCacheExpired(c *gin.Context, lastTime time.Time) bool {
|
||||||
eTag := helper.StringMd5(lastTime.Format(tmp))
|
eTag := str.Md5(lastTime.Format(tmp))
|
||||||
since := c.Request.Header.Get("If-Modified-Since")
|
since := c.Request.Header.Get("If-Modified-Since")
|
||||||
cTag := c.Request.Header.Get("If-None-Match")
|
cTag := c.Request.Header.Get("If-None-Match")
|
||||||
if since != "" && cTag != "" {
|
if since != "" && cTag != "" {
|
||||||
|
@ -41,7 +41,7 @@ func Feed(c *gin.Context) {
|
||||||
|
|
||||||
func setFeed(s string, c *gin.Context, t time.Time) {
|
func setFeed(s string, c *gin.Context, t time.Time) {
|
||||||
lastTimeGMT := t.Format(tmp)
|
lastTimeGMT := t.Format(tmp)
|
||||||
eTag := helper.StringMd5(lastTimeGMT)
|
eTag := str.Md5(lastTimeGMT)
|
||||||
c.Header("Content-Type", "application/rss+xml; charset=UTF-8")
|
c.Header("Content-Type", "application/rss+xml; charset=UTF-8")
|
||||||
c.Header("Last-Modified", lastTimeGMT)
|
c.Header("Last-Modified", lastTimeGMT)
|
||||||
c.Header("ETag", eTag)
|
c.Header("ETag", eTag)
|
||||||
|
|
|
@ -2,7 +2,8 @@ package actions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
||||||
dao "github.com/fthvgb1/wp-go/internal/pkg/dao"
|
dao "github.com/fthvgb1/wp-go/internal/pkg/dao"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||||
|
@ -83,7 +84,7 @@ func (h *indexHandle) getSearchKey() string {
|
||||||
|
|
||||||
func (h *indexHandle) parseParams() (err error) {
|
func (h *indexHandle) parseParams() (err error) {
|
||||||
h.order = h.c.Query("order")
|
h.order = h.c.Query("order")
|
||||||
if !helper.IsContainInArr(h.order, []string{"asc", "desc"}) {
|
if !slice.IsContained(h.order, []string{"asc", "desc"}) {
|
||||||
h.order = "asc"
|
h.order = "asc"
|
||||||
}
|
}
|
||||||
year := h.c.Param("year")
|
year := h.c.Param("year")
|
||||||
|
@ -142,7 +143,7 @@ func (h *indexHandle) parseParams() (err error) {
|
||||||
}
|
}
|
||||||
s := h.c.Query("s")
|
s := h.c.Query("s")
|
||||||
if s != "" && strings.Replace(s, " ", "", -1) != "" {
|
if s != "" && strings.Replace(s, " ", "", -1) != "" {
|
||||||
q := helper.StrJoin("%", s, "%")
|
q := str.Join("%", s, "%")
|
||||||
h.where = append(h.where, []string{
|
h.where = append(h.where, []string{
|
||||||
"and", "post_title", "like", q, "",
|
"and", "post_title", "like", q, "",
|
||||||
"or", "post_content", "like", q, "",
|
"or", "post_content", "like", q, "",
|
||||||
|
@ -150,7 +151,7 @@ func (h *indexHandle) parseParams() (err error) {
|
||||||
}, []string{"post_password", ""})
|
}, []string{"post_password", ""})
|
||||||
h.postType = append(h.postType, "page", "attachment")
|
h.postType = append(h.postType, "page", "attachment")
|
||||||
h.header = fmt.Sprintf("%s的搜索结果", s)
|
h.header = fmt.Sprintf("%s的搜索结果", s)
|
||||||
h.setTitleLR(helper.StrJoin(`"`, s, `"`, "的搜索结果"), wpconfig.Options.Value("blogname"))
|
h.setTitleLR(str.Join(`"`, s, `"`, "的搜索结果"), wpconfig.Options.Value("blogname"))
|
||||||
h.search = s
|
h.search = s
|
||||||
h.scene = plugins.Search
|
h.scene = plugins.Search
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package actions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/internal/phpass"
|
"github.com/fthvgb1/wp-go/internal/phpass"
|
||||||
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
||||||
"github.com/gin-contrib/sessions"
|
"github.com/gin-contrib/sessions"
|
||||||
|
@ -33,7 +33,7 @@ func Login(c *gin.Context) {
|
||||||
c.Error(err)
|
c.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cohash := fmt.Sprintf("wp-postpass_%s", helper.StringMd5(wpconfig.Options.Value("siteurl")))
|
cohash := fmt.Sprintf("wp-postpass_%s", str.Md5(wpconfig.Options.Value("siteurl")))
|
||||||
c.SetCookie(cohash, pass, 24*3600, "/", "", false, false)
|
c.SetCookie(cohash, pass, 24*3600, "/", "", false, false)
|
||||||
|
|
||||||
c.Redirect(http.StatusFound, ref)
|
c.Redirect(http.StatusFound, ref)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -35,7 +35,7 @@ func FlowLimit(maxRequestSleepNum, maxRequestNum int64, sleepTime []time.Duratio
|
||||||
n := atomic.LoadInt64(&flow)
|
n := atomic.LoadInt64(&flow)
|
||||||
if n >= atomic.LoadInt64(&maxRequestSleepNum) && n <= atomic.LoadInt64(&maxRequestNum) {
|
if n >= atomic.LoadInt64(&maxRequestSleepNum) && n <= atomic.LoadInt64(&maxRequestNum) {
|
||||||
ss := s.Load()
|
ss := s.Load()
|
||||||
t := helper.RandNum(ss[0], ss[1])
|
t := number.Rand(ss[0], ss[1])
|
||||||
time.Sleep(t)
|
time.Sleep(t)
|
||||||
} else if n > atomic.LoadInt64(&maxRequestNum) {
|
} else if n > atomic.LoadInt64(&maxRequestNum) {
|
||||||
c.String(http.StatusForbidden, "请求太多了,服务器君表示压力山大==!, 请稍后访问")
|
c.String(http.StatusForbidden, "请求太多了,服务器君表示压力山大==!, 请稍后访问")
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetStaticFileCache(c *gin.Context) {
|
func SetStaticFileCache(c *gin.Context) {
|
||||||
f := strings.Split(strings.TrimLeft(c.FullPath(), "/"), "/")
|
f := strings.Split(strings.TrimLeft(c.FullPath(), "/"), "/")
|
||||||
if len(f) > 0 && helper.IsContainInArr(f[0], []string{"wp-includes", "wp-content", "favicon.ico"}) {
|
if len(f) > 0 && slice.IsContained(f[0], []string{"wp-includes", "wp-content", "favicon.ico"}) {
|
||||||
c.Header("Cache-Control", "private, max-age=86400")
|
c.Header("Cache-Control", "private, max-age=86400")
|
||||||
}
|
}
|
||||||
c.Next()
|
c.Next()
|
||||||
|
|
|
@ -3,7 +3,7 @@ package phpass
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
@ -49,7 +49,7 @@ func (p *PasswordHash) getRandomBytes(count int) (r string, err error) {
|
||||||
if len(buf) < count {
|
if len(buf) < count {
|
||||||
r = ""
|
r = ""
|
||||||
for i := 0; i < count; i = i + 16 {
|
for i := 0; i < count; i = i + 16 {
|
||||||
p.randomState = helper.StringMd5(fmt.Sprintf("%d%s", time.Now().UnixMilli(), p.randomState))
|
p.randomState = str.Md5(fmt.Sprintf("%d%s", time.Now().UnixMilli(), p.randomState))
|
||||||
|
|
||||||
n, err := md5Raw(p.randomState)
|
n, err := md5Raw(p.randomState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
12
internal/pkg/cache/feed.go
vendored
12
internal/pkg/cache/feed.go
vendored
|
@ -3,7 +3,7 @@ package cache
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/cache"
|
"github.com/fthvgb1/wp-go/cache"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/internal/plugins"
|
"github.com/fthvgb1/wp-go/internal/plugins"
|
||||||
|
@ -47,7 +47,7 @@ func PostFeedCache() *cache.MapCache[string, string] {
|
||||||
func feed(arg ...any) (xml []string, err error) {
|
func feed(arg ...any) (xml []string, err error) {
|
||||||
c := arg[0].(*gin.Context)
|
c := arg[0].(*gin.Context)
|
||||||
r := RecentPosts(c, 10)
|
r := RecentPosts(c, 10)
|
||||||
ids := helper.SliceMap(r, func(t models.Posts) uint64 {
|
ids := slice.Map(r, func(t models.Posts) uint64 {
|
||||||
return t.Id
|
return t.Id
|
||||||
})
|
})
|
||||||
posts, err := GetPostsByIds(c, ids)
|
posts, err := GetPostsByIds(c, ids)
|
||||||
|
@ -56,7 +56,7 @@ func feed(arg ...any) (xml []string, err error) {
|
||||||
}
|
}
|
||||||
rs := templateRss
|
rs := templateRss
|
||||||
rs.LastBuildDate = time.Now().Format(timeFormat)
|
rs.LastBuildDate = time.Now().Format(timeFormat)
|
||||||
rs.Items = helper.SliceMap(posts, func(t models.Posts) rss2.Item {
|
rs.Items = slice.Map(posts, func(t models.Posts) rss2.Item {
|
||||||
desc := "无法提供摘要。这是一篇受保护的文章。"
|
desc := "无法提供摘要。这是一篇受保护的文章。"
|
||||||
plugins.PasswordProjectTitle(&t)
|
plugins.PasswordProjectTitle(&t)
|
||||||
if t.PostPassword != "" {
|
if t.PostPassword != "" {
|
||||||
|
@ -138,7 +138,7 @@ func postFeed(arg ...any) (x string, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rs.Items = helper.SliceMap(comments, func(t models.Comments) rss2.Item {
|
rs.Items = slice.Map(comments, func(t models.Comments) rss2.Item {
|
||||||
return rss2.Item{
|
return rss2.Item{
|
||||||
Title: fmt.Sprintf("评价者:%s", t.CommentAuthor),
|
Title: fmt.Sprintf("评价者:%s", t.CommentAuthor),
|
||||||
Link: fmt.Sprintf("%s/p/%d#comment-%d", wpconfig.Options.Value("siteurl"), post.Id, t.CommentId),
|
Link: fmt.Sprintf("%s/p/%d#comment-%d", wpconfig.Options.Value("siteurl"), post.Id, t.CommentId),
|
||||||
|
@ -161,13 +161,13 @@ func commentsFeed(args ...any) (r []string, err error) {
|
||||||
rs.Title = fmt.Sprintf("\"%s\"的评论", wpconfig.Options.Value("blogname"))
|
rs.Title = fmt.Sprintf("\"%s\"的评论", wpconfig.Options.Value("blogname"))
|
||||||
rs.LastBuildDate = time.Now().Format(timeFormat)
|
rs.LastBuildDate = time.Now().Format(timeFormat)
|
||||||
rs.AtomLink = fmt.Sprintf("%s/comments/feed", wpconfig.Options.Value("siteurl"))
|
rs.AtomLink = fmt.Sprintf("%s/comments/feed", wpconfig.Options.Value("siteurl"))
|
||||||
com, err := GetCommentByIds(c, helper.SliceMap(commens, func(t models.Comments) uint64 {
|
com, err := GetCommentByIds(c, slice.Map(commens, func(t models.Comments) uint64 {
|
||||||
return t.CommentId
|
return t.CommentId
|
||||||
}))
|
}))
|
||||||
if nil != err {
|
if nil != err {
|
||||||
return []string{}, err
|
return []string{}, err
|
||||||
}
|
}
|
||||||
rs.Items = helper.SliceMap(com, func(t models.Comments) rss2.Item {
|
rs.Items = slice.Map(com, func(t models.Comments) rss2.Item {
|
||||||
post, _ := GetPostById(c, t.CommentPostId)
|
post, _ := GetPostById(c, t.CommentPostId)
|
||||||
plugins.PasswordProjectTitle(&post)
|
plugins.PasswordProjectTitle(&post)
|
||||||
desc := "评论受保护:要查看请输入密码。"
|
desc := "评论受保护:要查看请输入密码。"
|
||||||
|
|
6
internal/pkg/cache/posts.go
vendored
6
internal/pkg/cache/posts.go
vendored
|
@ -3,7 +3,7 @@ package cache
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -67,10 +67,10 @@ func GetMonthPostIds(ctx context.Context, year, month string, page, limit int, o
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if order == "desc" {
|
if order == "desc" {
|
||||||
res = helper.SliceReverse(res)
|
res = slice.Reverse(res)
|
||||||
}
|
}
|
||||||
total = len(res)
|
total = len(res)
|
||||||
rr := helper.SlicePagination(res, page, limit)
|
rr := slice.Pagination(res, page, limit)
|
||||||
r, err = GetPostsByIds(ctx, rr)
|
r, err = GetPostsByIds(ctx, rr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package common
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -36,7 +37,7 @@ func PostComments(args ...any) ([]uint64, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return helper.SliceMap(r, func(t models.Comments) uint64 {
|
return slice.Map(r, func(t models.Comments) uint64 {
|
||||||
return t.CommentId
|
return t.CommentId
|
||||||
}), err
|
}), err
|
||||||
}
|
}
|
||||||
|
@ -47,11 +48,11 @@ func GetCommentByIds(args ...any) (map[uint64]models.Comments, error) {
|
||||||
m := make(map[uint64]models.Comments)
|
m := make(map[uint64]models.Comments)
|
||||||
r, err := model.SimpleFind[models.Comments](ctx, model.SqlBuilder{
|
r, err := model.SimpleFind[models.Comments](ctx, model.SqlBuilder{
|
||||||
{"comment_ID", "in", ""}, {"comment_approved", "1"},
|
{"comment_ID", "in", ""}, {"comment_approved", "1"},
|
||||||
}, "*", helper.SliceMap(ids, helper.ToAny[uint64]))
|
}, "*", slice.Map(ids, helper.ToAny[uint64]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
return helper.SimpleSliceToMap(r, func(t models.Comments) uint64 {
|
return slice.SimpleToMap(r, func(t models.Comments) uint64 {
|
||||||
return t.CommentId
|
return t.CommentId
|
||||||
}), err
|
}), err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
|
@ -17,7 +19,7 @@ func GetPostMetaByPostIds(args ...any) (r map[uint64]map[string]any, err error)
|
||||||
ids := args[1].([]uint64)
|
ids := args[1].([]uint64)
|
||||||
rr, err := model.Find[models.Postmeta](ctx, model.SqlBuilder{
|
rr, err := model.Find[models.Postmeta](ctx, model.SqlBuilder{
|
||||||
{"post_id", "in", ""},
|
{"post_id", "in", ""},
|
||||||
}, "*", "", nil, nil, nil, 0, helper.SliceMap(ids, helper.ToAny[uint64]))
|
}, "*", "", nil, nil, nil, 0, slice.Map(ids, helper.ToAny[uint64]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -76,7 +78,7 @@ func thumbnail(metadata models.WpAttachmentMetadata, thumbType, host string) (r
|
||||||
r.Width = metadata.Sizes[thumbType].Width
|
r.Width = metadata.Sizes[thumbType].Width
|
||||||
r.Height = metadata.Sizes[thumbType].Height
|
r.Height = metadata.Sizes[thumbType].Height
|
||||||
up := strings.Split(metadata.File, "/")
|
up := strings.Split(metadata.File, "/")
|
||||||
r.Srcset = strings.Join(helper.MapToSlice[string](metadata.Sizes, func(s string, size models.MetaDataFileSize) (r string, ok bool) {
|
r.Srcset = strings.Join(maps.FilterToSlice[string](metadata.Sizes, func(s string, size models.MetaDataFileSize) (r string, ok bool) {
|
||||||
up[2] = size.File
|
up[2] = size.File
|
||||||
if s == "post-thumbnail" {
|
if s == "post-thumbnail" {
|
||||||
return
|
return
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||||
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
||||||
"github.com/fthvgb1/wp-go/model"
|
"github.com/fthvgb1/wp-go/model"
|
||||||
|
@ -17,7 +18,7 @@ func GetPostsByIds(ids ...any) (m map[uint64]models.Posts, err error) {
|
||||||
ctx := ids[0].(context.Context)
|
ctx := ids[0].(context.Context)
|
||||||
m = make(map[uint64]models.Posts)
|
m = make(map[uint64]models.Posts)
|
||||||
id := ids[1].([]uint64)
|
id := ids[1].([]uint64)
|
||||||
arg := helper.SliceMap(id, helper.ToAny[uint64])
|
arg := slice.Map(id, helper.ToAny[uint64])
|
||||||
rawPosts, err := model.Find[models.Posts](ctx, model.SqlBuilder{{
|
rawPosts, err := model.Find[models.Posts](ctx, model.SqlBuilder{{
|
||||||
"Id", "in", "",
|
"Id", "in", "",
|
||||||
}}, "a.*,ifnull(d.name,'') category_name,ifnull(taxonomy,'') `taxonomy`", "", nil, model.SqlBuilder{{
|
}}, "a.*,ifnull(d.name,'') category_name,ifnull(taxonomy,'') `taxonomy`", "", nil, model.SqlBuilder{{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/leeqvip/gophp"
|
"github.com/leeqvip/gophp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ func (p Postmeta) AttachmentMetadata() (r WpAttachmentMetadata, err error) {
|
||||||
}
|
}
|
||||||
info, ok := unSerialize.(map[string]any)
|
info, ok := unSerialize.(map[string]any)
|
||||||
if ok {
|
if ok {
|
||||||
r, err = helper.StrAnyMapToStruct[WpAttachmentMetadata](info)
|
r, err = maps.StrAnyMapToStruct[WpAttachmentMetadata](info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -42,7 +42,7 @@ func AttachmentMetadata(s string) (r WpAttachmentMetadata, err error) {
|
||||||
}
|
}
|
||||||
info, ok := unSerialize.(map[string]any)
|
info, ok := unSerialize.(map[string]any)
|
||||||
if ok {
|
if ok {
|
||||||
r, err = helper.StrAnyMapToStruct[WpAttachmentMetadata](info)
|
r, err = maps.StrAnyMapToStruct[WpAttachmentMetadata](info)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
"github.com/fthvgb1/wp-go/internal/wpconfig"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -16,7 +16,7 @@ func Gravatar(email string, isTls bool) (u string) {
|
||||||
num := rand.Intn(3)
|
num := rand.Intn(3)
|
||||||
h := ""
|
h := ""
|
||||||
if email != "" {
|
if email != "" {
|
||||||
h = helper.StringMd5(strings.ToLower(email))
|
h = str.Md5(strings.ToLower(email))
|
||||||
num = int(h[0] % 3)
|
num = int(h[0] % 3)
|
||||||
}
|
}
|
||||||
if isTls {
|
if isTls {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package plugins
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -65,5 +65,5 @@ func (p PageEle) Url(path, query string, page int) string {
|
||||||
if path == "" {
|
if path == "" {
|
||||||
path = "/"
|
path = "/"
|
||||||
}
|
}
|
||||||
return helper.StrJoin(path, query)
|
return str.Join(path, query)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package twentyseventeen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/elliotchance/phpserialize"
|
"github.com/elliotchance/phpserialize"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/maps"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
"github.com/fthvgb1/wp-go/internal/pkg/cache"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
"github.com/fthvgb1/wp-go/internal/pkg/logs"
|
||||||
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
"github.com/fthvgb1/wp-go/internal/pkg/models"
|
||||||
|
@ -86,8 +86,8 @@ func getHeaderMarkup() (r HeaderImageMeta, err error) {
|
||||||
if ok {
|
if ok {
|
||||||
err = phpserialize.Unmarshal([]byte(mods), &rr)
|
err = phpserialize.Unmarshal([]byte(mods), &rr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rx := helper.MapAnyAnyToStrAny(rr)
|
rx := maps.AnyAnyToStrAny(rr)
|
||||||
r, err = helper.StrAnyMapToStruct[HeaderImageMeta](rx)
|
r, err = maps.StrAnyMapToStruct[HeaderImageMeta](rx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
@ -2,7 +2,7 @@ package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -25,7 +25,7 @@ func (w SqlBuilder) parseField(ss []string, s *strings.Builder) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w SqlBuilder) parseIn(ss []string, s *strings.Builder, c *int, args *[]any, in *[][]any) (t bool) {
|
func (w SqlBuilder) parseIn(ss []string, s *strings.Builder, c *int, args *[]any, in *[][]any) (t bool) {
|
||||||
if helper.IsContainInArr(ss[1], []string{"in", "not in"}) && len(*in) > 0 {
|
if slice.IsContained(ss[1], []string{"in", "not in"}) && len(*in) > 0 {
|
||||||
s.WriteString(" (")
|
s.WriteString(" (")
|
||||||
for _, p := range (*in)[*c] {
|
for _, p := range (*in)[*c] {
|
||||||
s.WriteString("?,")
|
s.WriteString("?,")
|
||||||
|
@ -148,7 +148,7 @@ func (w SqlBuilder) ParseWhere(in *[][]any) (string, []any, error) {
|
||||||
func (w SqlBuilder) parseOrderBy() string {
|
func (w SqlBuilder) parseOrderBy() string {
|
||||||
s := strings.Builder{}
|
s := strings.Builder{}
|
||||||
for _, ss := range w {
|
for _, ss := range w {
|
||||||
if len(ss) == 2 && ss[0] != "" && helper.IsContainInArr(ss[1], []string{"asc", "desc"}) {
|
if len(ss) == 2 && ss[0] != "" && slice.IsContained(ss[1], []string{"asc", "desc"}) {
|
||||||
s.WriteString(" ")
|
s.WriteString(" ")
|
||||||
s.WriteString(ss[0])
|
s.WriteString(ss[0])
|
||||||
s.WriteString(" ")
|
s.WriteString(" ")
|
||||||
|
|
|
@ -3,7 +3,7 @@ package model
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -87,7 +87,7 @@ func SimplePagination[T Model](ctx context.Context, where ParseWhere, fields, gr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindOneById[T Model, I helper.IntNumber](ctx context.Context, id I) (T, error) {
|
func FindOneById[T Model, I number.IntNumber](ctx context.Context, id I) (T, error) {
|
||||||
var r T
|
var r T
|
||||||
sql := fmt.Sprintf("select * from `%s` where `%s`=?", r.Table(), r.PrimaryKey())
|
sql := fmt.Sprintf("select * from `%s` where `%s`=?", r.Table(), r.PrimaryKey())
|
||||||
err := globalBb.Get(ctx, &r, sql, id)
|
err := globalBb.Get(ctx, &r, sql, id)
|
||||||
|
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -497,10 +499,10 @@ func TestSimplePagination(t *testing.T) {
|
||||||
order: nil,
|
order: nil,
|
||||||
join: nil,
|
join: nil,
|
||||||
having: nil,
|
having: nil,
|
||||||
in: [][]any{helper.SliceMap[int, any](helper.RangeSlice(431, 440, 1), helper.ToAny[int])},
|
in: [][]any{slice.Map[int, any](number.Range(431, 440, 1), helper.ToAny[int])},
|
||||||
},
|
},
|
||||||
wantR: func() (r []post) {
|
wantR: func() (r []post) {
|
||||||
r, err := Select[post](ctx, "select * from "+post{}.Table()+" where ID in (?,?,?,?,?)", helper.SliceMap[int, any](helper.RangeSlice(431, 435, 1), helper.ToAny[int])...)
|
r, err := Select[post](ctx, "select * from "+post{}.Table()+" where ID in (?,?,?,?,?)", slice.Map[int, any](number.Range(431, 435, 1), helper.ToAny[int])...)
|
||||||
if err != nil && err != sql.ErrNoRows {
|
if err != nil && err != sql.ErrNoRows {
|
||||||
panic(err)
|
panic(err)
|
||||||
} else if err == sql.ErrNoRows {
|
} else if err == sql.ErrNoRows {
|
||||||
|
|
|
@ -2,7 +2,8 @@ package digest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/html"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
@ -17,7 +18,7 @@ func ClearHtml(str string) string {
|
||||||
content := removeWpBlock.ReplaceAllString(str, "")
|
content := removeWpBlock.ReplaceAllString(str, "")
|
||||||
content = strings.Trim(content, " \t\n\r\000\x0B")
|
content = strings.Trim(content, " \t\n\r\000\x0B")
|
||||||
content = strings.Replace(content, "]]>", "]]>", -1)
|
content = strings.Replace(content, "]]>", "]]>", -1)
|
||||||
content = helper.StripTagsX(content, "<a><b><blockquote><br><cite><code><dd><del><div><dl><dt><em><h1><h2><h3><h4><h5><h6><i><img><li><ol><p><pre><span><strong><ul>")
|
content = html.StripTagsX(content, "<a><b><blockquote><br><cite><code><dd><del><div><dl><dt><em><h1><h2><h3><h4><h5><h6><i><img><li><ol><p><pre><span><strong><ul>")
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ func Raw(str string, limit int, u string) string {
|
||||||
content := removeWpBlock.ReplaceAllString(str, "")
|
content := removeWpBlock.ReplaceAllString(str, "")
|
||||||
content = strings.Trim(content, " \t\n\r\000\x0B")
|
content = strings.Trim(content, " \t\n\r\000\x0B")
|
||||||
content = strings.Replace(content, "]]>", "]]>", -1)
|
content = strings.Replace(content, "]]>", "]]>", -1)
|
||||||
content = helper.StripTagsX(content, "<a><b><blockquote><br><cite><code><dd><del><div><dl><dt><em><h1><h2><h3><h4><h5><h6><i><img><li><ol><p><pre><span><strong><ul>")
|
content = html.StripTagsX(content, "<a><b><blockquote><br><cite><code><dd><del><div><dl><dt><em><h1><h2><h3><h4><h5><h6><i><img><li><ol><p><pre><span><strong><ul>")
|
||||||
length := utf8.RuneCountInString(content) + 1
|
length := utf8.RuneCountInString(content) + 1
|
||||||
if length > limit {
|
if length > limit {
|
||||||
index := quto.FindAllStringIndex(content, -1)
|
index := quto.FindAllStringIndex(content, -1)
|
||||||
|
@ -43,7 +44,7 @@ func Raw(str string, limit int, u string) string {
|
||||||
for {
|
for {
|
||||||
i++
|
i++
|
||||||
for len(index) > 0 {
|
for len(index) > 0 {
|
||||||
ints := helper.SliceMap(index[0], func(t int) int {
|
ints := slice.Map(index[0], func(t int) int {
|
||||||
return utf8.RuneCountInString(content[:t])
|
return utf8.RuneCountInString(content[:t])
|
||||||
})
|
})
|
||||||
if ints[0] <= i {
|
if ints[0] <= i {
|
||||||
|
@ -75,7 +76,7 @@ func Raw(str string, limit int, u string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
content = string(ru[:i])
|
content = string(ru[:i])
|
||||||
closeTag := helper.CloseHtmlTag(content)
|
closeTag := html.CloseTag(content)
|
||||||
tmp := `%s......%s<p class="read-more"><a href="%s">继续阅读</a></p>`
|
tmp := `%s......%s<p class="read-more"><a href="%s">继续阅读</a></p>`
|
||||||
if strings.Contains(closeTag, "pre") || strings.Contains(closeTag, "code") {
|
if strings.Contains(closeTag, "pre") || strings.Contains(closeTag, "code") {
|
||||||
tmp = `%s%s......<p class="read-more"><a href="%s">继续阅读</a></p>`
|
tmp = `%s%s......<p class="read-more"><a href="%s">继续阅读</a></p>`
|
||||||
|
|
|
@ -2,7 +2,7 @@ package rss2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -101,7 +101,7 @@ func (r Rss2) GetXML() (xml string) {
|
||||||
"{$updatePeriod}": r.UpdatePeriod,
|
"{$updatePeriod}": r.UpdatePeriod,
|
||||||
"{$updateFrequency}": fmt.Sprintf("%d", r.UpdateFrequency),
|
"{$updateFrequency}": fmt.Sprintf("%d", r.UpdateFrequency),
|
||||||
"{$generator}": r.Generator,
|
"{$generator}": r.Generator,
|
||||||
"{$items}": strings.Join(helper.SliceMap(r.Items, func(t Item) string {
|
"{$items}": strings.Join(slice.Map(r.Items, func(t Item) string {
|
||||||
return t.GetXml()
|
return t.GetXml()
|
||||||
}), ""),
|
}), ""),
|
||||||
} {
|
} {
|
||||||
|
|
|
@ -2,7 +2,7 @@ package safety
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -20,7 +20,7 @@ func TestSlice_Append(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
r: *NewSlice([]int{}),
|
r: *NewSlice([]int{}),
|
||||||
args: args[int]{helper.RangeSlice(1, 10, 1)},
|
args: args[int]{number.Range(1, 10, 1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
|
@ -2,7 +2,8 @@ package stream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -33,8 +34,8 @@ func TestNewSimpleMapStream(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var y = helper.RangeSlice(1, 1000, 1)
|
var y = number.Range(1, 1000, 1)
|
||||||
var w = helper.SliceToMap(y, func(v int) (int, int) {
|
var w = slice.ToMap(y, func(v int) (int, int) {
|
||||||
return v, v
|
return v, v
|
||||||
}, true)
|
}, true)
|
||||||
|
|
||||||
|
@ -101,7 +102,7 @@ func TestSimpleMapParallelFilterAndMapToMap(t *testing.T) {
|
||||||
},
|
},
|
||||||
c: 6,
|
c: 6,
|
||||||
},
|
},
|
||||||
want: NewSimpleMapStream(helper.SliceToMap(y[500:], func(v int) (K, T string) {
|
want: NewSimpleMapStream(slice.ToMap(y[500:], func(v int) (K, T string) {
|
||||||
t := strconv.Itoa(v)
|
t := strconv.Itoa(v)
|
||||||
return t, t
|
return t, t
|
||||||
}, true)),
|
}, true)),
|
||||||
|
@ -139,7 +140,7 @@ func TestSimpleMapStreamFilterAndMapToMap(t *testing.T) {
|
||||||
return "", "", false
|
return "", "", false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantR: NewSimpleMapStream(helper.SliceToMap(y[500:], func(v int) (K, T string) {
|
wantR: NewSimpleMapStream(slice.ToMap(y[500:], func(v int) (K, T string) {
|
||||||
t := strconv.Itoa(v)
|
t := strconv.Itoa(v)
|
||||||
return t, t
|
return t, t
|
||||||
}, true)),
|
}, true)),
|
||||||
|
@ -166,7 +167,7 @@ func TestSimpleMapStream_ForEach(t *testing.T) {
|
||||||
tests := []testCase[int, int]{
|
tests := []testCase[int, int]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
r: NewSimpleMapStream(helper.SliceToMap(y[0:10], func(v int) (int, int) {
|
r: NewSimpleMapStream(slice.ToMap(y[0:10], func(v int) (int, int) {
|
||||||
return v, v
|
return v, v
|
||||||
}, true)),
|
}, true)),
|
||||||
args: args[int, int]{
|
args: args[int, int]{
|
||||||
|
@ -243,10 +244,10 @@ func TestSimpleMapStream_Result(t *testing.T) {
|
||||||
tests := []testCase[int, int]{
|
tests := []testCase[int, int]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
r: NewSimpleMapStream(helper.SliceToMap(y, func(v int) (int, int) {
|
r: NewSimpleMapStream(slice.ToMap(y, func(v int) (int, int) {
|
||||||
return v, v
|
return v, v
|
||||||
}, true)),
|
}, true)),
|
||||||
want: helper.SliceToMap(y, func(v int) (int, int) {
|
want: slice.ToMap(y, func(v int) (int, int) {
|
||||||
return v, v
|
return v, v
|
||||||
}, true),
|
}, true),
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package stream
|
package stream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"github.com/fthvgb1/wp-go/safety"
|
"github.com/fthvgb1/wp-go/safety"
|
||||||
"github.com/fthvgb1/wp-go/taskPools"
|
"github.com/fthvgb1/wp-go/taskPools"
|
||||||
)
|
)
|
||||||
|
@ -47,7 +47,7 @@ func SimpleSliceFilterAndMapToMap[K comparable, V any, T any](a SimpleSliceStrea
|
||||||
}
|
}
|
||||||
|
|
||||||
func SimpleStreamFilterAndMap[R, T any](a SimpleSliceStream[T], fn func(T) (R, bool)) SimpleSliceStream[R] {
|
func SimpleStreamFilterAndMap[R, T any](a SimpleSliceStream[T], fn func(T) (R, bool)) SimpleSliceStream[R] {
|
||||||
return NewSimpleSliceStream(helper.SliceFilterAndMap(a.arr, fn))
|
return NewSimpleSliceStream(slice.FilterAndMap(a.arr, fn))
|
||||||
}
|
}
|
||||||
|
|
||||||
func SimpleParallelMap[R, T any](a SimpleSliceStream[T], fn func(T) R, c int) SimpleSliceStream[R] {
|
func SimpleParallelMap[R, T any](a SimpleSliceStream[T], fn func(T) R, c int) SimpleSliceStream[R] {
|
||||||
|
@ -59,11 +59,11 @@ func SimpleParallelMap[R, T any](a SimpleSliceStream[T], fn func(T) R, c int) Si
|
||||||
return SimpleSliceStream[R]{rr.Load()}
|
return SimpleSliceStream[R]{rr.Load()}
|
||||||
}
|
}
|
||||||
func SimpleStreamMap[R, T any](a SimpleSliceStream[T], fn func(T) R) SimpleSliceStream[R] {
|
func SimpleStreamMap[R, T any](a SimpleSliceStream[T], fn func(T) R) SimpleSliceStream[R] {
|
||||||
return NewSimpleSliceStream(helper.SliceMap(a.arr, fn))
|
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) {
|
func Reduce[T any, S any](s SimpleSliceStream[S], fn func(S, T) T, init T) (r T) {
|
||||||
return helper.SliceReduce(s.arr, fn, init)
|
return slice.Reduce(s.arr, fn, init)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSimpleSliceStream[T any](arr []T) SimpleSliceStream[T] {
|
func NewSimpleSliceStream[T any](arr []T) SimpleSliceStream[T] {
|
||||||
|
@ -101,7 +101,7 @@ func (r SimpleSliceStream[T]) ParallelFilter(fn func(T) bool, c int) SimpleSlice
|
||||||
return SimpleSliceStream[T]{rr.Load()}
|
return SimpleSliceStream[T]{rr.Load()}
|
||||||
}
|
}
|
||||||
func (r SimpleSliceStream[T]) Filter(fn func(T) bool) SimpleSliceStream[T] {
|
func (r SimpleSliceStream[T]) Filter(fn func(T) bool) SimpleSliceStream[T] {
|
||||||
r.arr = helper.SliceFilter(r.arr, fn)
|
r.arr = slice.Filter(r.arr, fn)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,12 +114,12 @@ func (r SimpleSliceStream[T]) ParallelMap(fn func(T) T, c int) SimpleSliceStream
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) Map(fn func(T) T) SimpleSliceStream[T] {
|
func (r SimpleSliceStream[T]) Map(fn func(T) T) SimpleSliceStream[T] {
|
||||||
r.arr = helper.SliceMap(r.arr, fn)
|
r.arr = slice.Map(r.arr, fn)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) Sort(fn func(i, j T) bool) SimpleSliceStream[T] {
|
func (r SimpleSliceStream[T]) Sort(fn func(i, j T) bool) SimpleSliceStream[T] {
|
||||||
helper.SimpleSort(r.arr, fn)
|
slice.SortSelf(r.arr, fn)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ func (r SimpleSliceStream[T]) Limit(limit, offset int) SimpleSliceStream[T] {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r SimpleSliceStream[T]) Reverse() SimpleSliceStream[T] {
|
func (r SimpleSliceStream[T]) Reverse() SimpleSliceStream[T] {
|
||||||
helper.SliceSelfReverse(r.arr)
|
slice.ReverseSelf(r.arr)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,14 @@ package stream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/fthvgb1/wp-go/helper"
|
"github.com/fthvgb1/wp-go/helper/number"
|
||||||
|
"github.com/fthvgb1/wp-go/helper/slice"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var s = NewSimpleSliceStream(helper.RangeSlice(1, 10, 1))
|
var s = NewSimpleSliceStream(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 {
|
||||||
|
@ -32,7 +33,7 @@ func TestSimpleSliceStream_Filter(t *testing.T) {
|
||||||
return
|
return
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{helper.RangeSlice(6, 10, 1)},
|
want: SimpleSliceStream[int]{number.Range(6, 10, 1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -90,7 +91,7 @@ func TestSimpleSliceStream_Limit(t *testing.T) {
|
||||||
limit: 3,
|
limit: 3,
|
||||||
offset: 5,
|
offset: 5,
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{helper.RangeSlice(6, 8, 1)},
|
want: SimpleSliceStream[int]{number.Range(6, 8, 1)},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "t2",
|
name: "t2",
|
||||||
|
@ -99,7 +100,7 @@ func TestSimpleSliceStream_Limit(t *testing.T) {
|
||||||
limit: 3,
|
limit: 3,
|
||||||
offset: 9,
|
offset: 9,
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{helper.RangeSlice(10, 10, 1)},
|
want: SimpleSliceStream[int]{number.Range(10, 10, 1)},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "t3",
|
name: "t3",
|
||||||
|
@ -139,7 +140,7 @@ func TestSimpleSliceStream_Map(t *testing.T) {
|
||||||
return t * 2
|
return t * 2
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{helper.RangeSlice(2, 20, 2)},
|
want: SimpleSliceStream[int]{number.Range(2, 20, 2)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -161,7 +162,7 @@ func TestSimpleSliceStream_Result(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
r: s,
|
r: s,
|
||||||
want: helper.RangeSlice(1, 10, 1),
|
want: number.Range(1, 10, 1),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -192,7 +193,7 @@ func TestSimpleSliceStream_Sort(t *testing.T) {
|
||||||
return i > j
|
return i > j
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{helper.RangeSlice(10, 1, -1)},
|
want: SimpleSliceStream[int]{number.Range(10, 1, -1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -254,7 +255,7 @@ func TestSimpleSliceStream_ParallelFilter(t *testing.T) {
|
||||||
},
|
},
|
||||||
c: 6,
|
c: 6,
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{helper.RangeSlice(4, 10, 1)},
|
want: SimpleSliceStream[int]{number.Range(4, 10, 1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -289,7 +290,7 @@ func TestSimpleSliceStream_ParallelMap(t *testing.T) {
|
||||||
},
|
},
|
||||||
c: 6,
|
c: 6,
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[int]{helper.RangeSlice(2, 20, 2)},
|
want: SimpleSliceStream[int]{number.Range(2, 20, 2)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -323,7 +324,7 @@ func TestReduce(t *testing.T) {
|
||||||
},
|
},
|
||||||
0,
|
0,
|
||||||
},
|
},
|
||||||
wantR: helper.Sum(s.Result()...),
|
wantR: number.Sum(s.Result()...),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -344,8 +345,8 @@ func TestSimpleSliceStream_Reverse(t *testing.T) {
|
||||||
tests := []testCase[int]{
|
tests := []testCase[int]{
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
r: NewSimpleSliceStream(helper.RangeSlice(1, 10, 1)),
|
r: NewSimpleSliceStream(number.Range(1, 10, 1)),
|
||||||
want: SimpleSliceStream[int]{helper.RangeSlice(10, 1, -1)},
|
want: SimpleSliceStream[int]{number.Range(10, 1, -1)},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -357,7 +358,7 @@ func TestSimpleSliceStream_Reverse(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var x = helper.RangeSlice(1, 100000, 1)
|
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 {
|
||||||
|
@ -377,7 +378,7 @@ func TestSimpleStreamMap(t *testing.T) {
|
||||||
fn: strconv.Itoa,
|
fn: strconv.Itoa,
|
||||||
},
|
},
|
||||||
want: SimpleSliceStream[string]{
|
want: SimpleSliceStream[string]{
|
||||||
helper.SliceMap(x, strconv.Itoa),
|
slice.Map(x, strconv.Itoa),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -406,7 +407,7 @@ func TestSimpleParallelMap(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args[string, int]{
|
args: args[string, int]{
|
||||||
a: NewSimpleSliceStream(helper.SliceMap(x, strconv.Itoa)),
|
a: NewSimpleSliceStream(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
|
||||||
|
@ -442,7 +443,7 @@ func TestSimpleParallelFilterAndMap(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args[string, int]{
|
args: args[string, int]{
|
||||||
a: NewSimpleSliceStream(helper.SliceMap(x, strconv.Itoa)),
|
a: NewSimpleSliceStream(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 {
|
||||||
|
@ -480,7 +481,7 @@ func TestSimpleStreamFilterAndMap(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args[string, int]{
|
args: args[string, int]{
|
||||||
a: NewSimpleSliceStream(helper.SliceMap(x, strconv.Itoa)),
|
a: NewSimpleSliceStream(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 {
|
||||||
|
@ -547,7 +548,7 @@ func TestSimpleParallelFilterAndMapToMap(t *testing.T) {
|
||||||
},
|
},
|
||||||
c: 6,
|
c: 6,
|
||||||
},
|
},
|
||||||
wantR: NewSimpleMapStream(helper.SliceToMap(x[50000:], func(t int) (int, int) {
|
wantR: NewSimpleMapStream(slice.ToMap(x[50000:], func(t int) (int, int) {
|
||||||
return t, t
|
return t, t
|
||||||
}, true)),
|
}, true)),
|
||||||
},
|
},
|
||||||
|
@ -576,7 +577,7 @@ func TestSimpleSliceFilterAndMapToMap(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "t1",
|
name: "t1",
|
||||||
args: args[int, int, int]{
|
args: args[int, int, int]{
|
||||||
a: NewSimpleSliceStream(helper.RangeSlice(1, 10, 1)),
|
a: NewSimpleSliceStream(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
|
||||||
|
@ -584,7 +585,7 @@ func TestSimpleSliceFilterAndMapToMap(t *testing.T) {
|
||||||
return 0, 0, false
|
return 0, 0, false
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantR: NewSimpleMapStream(helper.SliceToMap(helper.RangeSlice(7, 10, 1), func(t int) (int, int) {
|
wantR: NewSimpleMapStream(slice.ToMap(number.Range(7, 10, 1), func(t int) (int, int) {
|
||||||
return t, t
|
return t, t
|
||||||
}, true)),
|
}, true)),
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user