From 4226a23a3979b3ccfaa223859e7a56fef88bc7f6 Mon Sep 17 00:00:00 2001 From: Hunk Zhu <54zhua@gmail.com> Date: Wed, 15 Oct 2025 15:08:26 +0800 Subject: [PATCH] feat(container/garray): add TArray (#4466) Add TArray[T] for wrapping Array --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- container/garray/garray_func.go | 48 + container/garray/garray_normal_t.go | 493 +++++++ .../garray/garray_z_example_normal_t_test.go | 1281 +++++++++++++++++ .../garray/garray_z_unit_normal_t_test.go | 851 +++++++++++ 4 files changed, 2673 insertions(+) create mode 100644 container/garray/garray_normal_t.go create mode 100644 container/garray/garray_z_example_normal_t_test.go create mode 100644 container/garray/garray_z_unit_normal_t_test.go diff --git a/container/garray/garray_func.go b/container/garray/garray_func.go index 155cca0d8..7144a48ed 100644 --- a/container/garray/garray_func.go +++ b/container/garray/garray_func.go @@ -67,3 +67,51 @@ func quickSortStr(values []string, comparator func(a, b string) int) { quickSortStr(values[:head], comparator) quickSortStr(values[head+1:], comparator) } + +// tToAnySlice converts []T to []any +func tToAnySlice[T comparable](values []T) []any { + if values == nil { + return nil + } + anyValues := make([]any, len(values), cap(values)) + for k, v := range values { + anyValues[k] = v + } + return anyValues +} + +// anyToTSlice is convert []any to []T +func anyToTSlice[T comparable](values []any) []T { + if values == nil { + return nil + } + tValues := make([]T, len(values), cap(values)) + for k, v := range values { + tValues[k], _ = v.(T) + } + return tValues +} + +// tToAnySlices converts [][]T to [][]any +func tToAnySlices[T comparable](values [][]T) [][]any { + if values == nil { + return nil + } + anyValues := make([][]any, len(values), cap(values)) + for k, v := range values { + anyValues[k] = tToAnySlice(v) + } + return anyValues +} + +// anyToTSlices converts [][]any to [][]T +func anyToTSlices[T comparable](values [][]any) [][]T { + if values == nil { + return nil + } + tValues := make([][]T, len(values), cap(values)) + for k, v := range values { + tValues[k] = anyToTSlice[T](v) + } + return tValues +} diff --git a/container/garray/garray_normal_t.go b/container/garray/garray_normal_t.go new file mode 100644 index 000000000..d10192dc0 --- /dev/null +++ b/container/garray/garray_normal_t.go @@ -0,0 +1,493 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package garray + +import ( + "github.com/gogf/gf/v2/util/gconv" +) + +// TArray is a golang array with rich features. +// It contains a concurrent-safe/unsafe switch, which should be set +// when its initialization and cannot be changed then. +// TArray is a wrapper of Array. It is designed to make using Array more convenient. +type TArray[T comparable] struct { + Array +} + +// NewTArray creates and returns an empty array. +// The parameter `safe` is used to specify whether using array in concurrent-safety, +// which is false in default. +func NewTArray[T comparable](safe ...bool) *TArray[T] { + return &TArray[T]{ + Array: *NewArray(safe...), + } +} + +// NewTArraySize create and returns an array with given size and cap. +// The parameter `safe` is used to specify whether using array in concurrent-safety, +// which is false in default. +func NewTArraySize[T comparable](size int, cap int, safe ...bool) *TArray[T] { + arr := NewArraySize(size, cap, safe...) + ret := &TArray[T]{ + Array: *arr, + } + return ret +} + +// NewTArrayFrom creates and returns an array with given slice `array`. +// The parameter `safe` is used to specify whether using array in concurrent-safety, +// which is false in default. +func NewTArrayFrom[T comparable](array []T, safe ...bool) *TArray[T] { + return &TArray[T]{ + Array: *NewArrayFrom(tToAnySlice(array), safe...), + } +} + +// NewTArrayFromCopy creates and returns an array from a copy of given slice `array`. +// The parameter `safe` is used to specify whether using array in concurrent-safety, +// which is false in default. +func NewTArrayFromCopy[T comparable](array []T, safe ...bool) *TArray[T] { + return &TArray[T]{ + Array: *NewArrayFromCopy(tToAnySlice(array), safe...), + } +} + +// At returns the value by the specified index. +// If the given `index` is out of range of the array, it returns `nil`. +func (a *TArray[T]) At(index int) (value T) { + value, _ = a.Array.At(index).(T) + return +} + +// Get returns the value by the specified index. +// If the given `index` is out of range of the array, the `found` is false. +func (a *TArray[T]) Get(index int) (value T, found bool) { + val, found := a.Array.Get(index) + if !found { + return + } + value, _ = val.(T) + return +} + +// Set sets value to specified index. +func (a *TArray[T]) Set(index int, value T) error { + return a.Array.Set(index, value) +} + +// SetArray sets the underlying slice array with the given `array`. +func (a *TArray[T]) SetArray(array []T) *TArray[T] { + a.Array.SetArray(tToAnySlice(array)) + return a +} + +// Replace replaces the array items by given `array` from the beginning of array. +func (a *TArray[T]) Replace(array []T) *TArray[T] { + a.Array.Replace(tToAnySlice(array)) + return a +} + +// Sum returns the sum of values in an array. +func (a *TArray[T]) Sum() int { + return a.Array.Sum() +} + +// SortFunc sorts the array by custom function `less`. +func (a *TArray[T]) SortFunc(less func(v1, v2 T) bool) *TArray[T] { + a.Array.SortFunc(func(v1, v2 any) bool { + v1t, _ := v1.(T) + v2t, _ := v2.(T) + return less(v1t, v2t) + }) + return a +} + +// InsertBefore inserts the `values` to the front of `index`. +func (a *TArray[T]) InsertBefore(index int, values ...T) error { + return a.Array.InsertBefore(index, tToAnySlice(values)...) +} + +// InsertAfter inserts the `values` to the back of `index`. +func (a *TArray[T]) InsertAfter(index int, values ...T) error { + return a.Array.InsertAfter(index, tToAnySlice(values)...) +} + +// Remove removes an item by index. +// If the given `index` is out of range of the array, the `found` is false. +func (a *TArray[T]) Remove(index int) (value T, found bool) { + val, found := a.Array.Remove(index) + if !found { + return + } + value, _ = val.(T) + return +} + +// RemoveValue removes an item by value. +// It returns true if value is found in the array, or else false if not found. +func (a *TArray[T]) RemoveValue(value T) bool { + return a.Array.RemoveValue(value) +} + +// RemoveValues removes multiple items by `values`. +func (a *TArray[T]) RemoveValues(values ...T) { + a.Array.RemoveValues(tToAnySlice(values)...) +} + +// PushLeft pushes one or multiple items to the beginning of array. +func (a *TArray[T]) PushLeft(value ...T) *TArray[T] { + a.Array.PushLeft(tToAnySlice(value)...) + return a +} + +// PushRight pushes one or multiple items to the end of array. +// It equals to Append. +func (a *TArray[T]) PushRight(value ...T) *TArray[T] { + a.Array.PushRight(tToAnySlice(value)...) + return a +} + +// PopRand randomly pops and return an item out of array. +// Note that if the array is empty, the `found` is false. +func (a *TArray[T]) PopRand() (value T, found bool) { + val, found := a.Array.PopRand() + if !found { + return + } + value, _ = val.(T) + return +} + +// PopRands randomly pops and returns `size` items out of array. +func (a *TArray[T]) PopRands(size int) []T { + return anyToTSlice[T](a.Array.PopRands(size)) +} + +// PopLeft pops and returns an item from the beginning of array. +// Note that if the array is empty, the `found` is false. +func (a *TArray[T]) PopLeft() (value T, found bool) { + val, found := a.Array.PopLeft() + if !found { + return + } + value, _ = val.(T) + return +} + +// PopRight pops and returns an item from the end of array. +// Note that if the array is empty, the `found` is false. +func (a *TArray[T]) PopRight() (value T, found bool) { + val, found := a.Array.PopRight() + if !found { + return + } + value, _ = val.(T) + return +} + +// PopLefts pops and returns `size` items from the beginning of array. +func (a *TArray[T]) PopLefts(size int) []T { + return anyToTSlice[T](a.Array.PopLefts(size)) +} + +// PopRights pops and returns `size` items from the end of array. +func (a *TArray[T]) PopRights(size int) []T { + return anyToTSlice[T](a.Array.PopRights(size)) +} + +// Range picks and returns items by range, like array[start:end]. +// Notice, if in concurrent-safe usage, it returns a copy of slice; +// else a pointer to the underlying data. +// +// If `end` is negative, then the offset will start from the end of array. +// If `end` is omitted, then the sequence will have everything from start up +// until the end of the array. +func (a *TArray[T]) Range(start int, end ...int) []T { + return anyToTSlice[T](a.Array.Range(start, end...)) +} + +// SubSlice returns a slice of elements from the array as specified +// by the `offset` and `size` parameters. +// If in concurrent safe usage, it returns a copy of the slice; else a pointer. +// +// If offset is non-negative, the sequence will start at that offset in the array. +// If offset is negative, the sequence will start that far from the end of the array. +// +// If length is given and is positive, then the sequence will have up to that many elements in it. +// If the array is shorter than the length, then only the available array elements will be present. +// If length is given and is negative then the sequence will stop that many elements from the end of the array. +// If it is omitted, then the sequence will have everything from offset up until the end of the array. +// +// Any possibility crossing the left border of array, it will fail. +func (a *TArray[T]) SubSlice(offset int, length ...int) []T { + return anyToTSlice[T](a.Array.SubSlice(offset, length...)) +} + +// Append is alias of PushRight, please See PushRight. +func (a *TArray[T]) Append(value ...T) *TArray[T] { + a.Array.Append(tToAnySlice(value)...) + return a +} + +// Len returns the length of array. +func (a *TArray[T]) Len() int { + return a.Array.Len() +} + +// Slice returns the underlying data of array. +// Note that, if it's in concurrent-safe usage, it returns a copy of underlying data, +// or else a pointer to the underlying data. +func (a *TArray[T]) Slice() []T { + return anyToTSlice[T](a.Array.Slice()) +} + +// Interfaces returns current array as []any. +func (a *TArray[T]) Interfaces() []any { + return a.Array.Interfaces() +} + +// Clone returns a new array, which is a copy of current array. +func (a *TArray[T]) Clone() *TArray[T] { + return &TArray[T]{ + Array: *a.Array.Clone(), + } +} + +// Clear deletes all items of current array. +func (a *TArray[T]) Clear() *TArray[T] { + a.Array.Clear() + return a +} + +// Contains checks whether a value exists in the array. +func (a *TArray[T]) Contains(value T) bool { + return a.Array.Contains(value) +} + +// Search searches array by `value`, returns the index of `value`, +// or returns -1 if not exists. +func (a *TArray[T]) Search(value T) int { + return a.Array.Search(value) +} + +// Unique uniques the array, clear repeated items. +// Example: [1,1,2,3,2] -> [1,2,3] +func (a *TArray[T]) Unique() *TArray[T] { + a.Array.Unique() + return a +} + +// LockFunc locks writing by callback function `f`. +func (a *TArray[T]) LockFunc(f func(array []T)) *TArray[T] { + a.Array.LockFunc(func(array []any) { + vals := anyToTSlice[T](array) + f(vals) + for k, v := range vals { + array[k] = v + } + }) + return a +} + +// RLockFunc locks reading by callback function `f`. +func (a *TArray[T]) RLockFunc(f func(array []T)) *TArray[T] { + a.Array.RLockFunc(func(array []any) { + f(anyToTSlice[T](array)) + }) + return a +} + +// Merge merges `array` into current array. +// The parameter `array` can be any garray or slice type. +// The difference between Merge and Append is Append supports only specified slice type, +// but Merge supports more parameter types. +func (a *TArray[T]) Merge(array any) *TArray[T] { + switch v := array.(type) { + case *Array: + return a.Merge(v.Slice()) + case *StrArray: + return a.Merge(v.Slice()) + case *IntArray: + return a.Merge(v.Slice()) + case *TArray[T]: + a.Array.Merge(&v.Array) + case []T: + a.Array.Merge(v) + case TArray[T]: + a.Array.Merge(&v.Array) + default: + var vals []T + if err := gconv.Scan(v, &vals); err != nil { + panic(err) + } + a.Append(vals...) + } + return a +} + +// Fill fills an array with num entries of the value `value`, +// keys starting at the `startIndex` parameter. +func (a *TArray[T]) Fill(startIndex int, num int, value T) error { + return a.Array.Fill(startIndex, num, value) +} + +// Chunk splits an array into multiple arrays, +// the size of each array is determined by `size`. +// The last chunk may contain less than size elements. +func (a *TArray[T]) Chunk(size int) (values [][]T) { + return anyToTSlices[T](a.Array.Chunk(size)) +} + +// Pad pads array to the specified length with `value`. +// If size is positive then the array is padded on the right, or negative on the left. +// If the absolute value of `size` is less than or equal to the length of the array +// then no padding takes place. +func (a *TArray[T]) Pad(size int, val T) *TArray[T] { + a.Array.Pad(size, val) + return a +} + +// Rand randomly returns one item from array(no deleting). +func (a *TArray[T]) Rand() (value T, found bool) { + val, found := a.Array.Rand() + if !found { + return + } + value, _ = val.(T) + return +} + +// Rands randomly returns `size` items from array(no deleting). +func (a *TArray[T]) Rands(size int) []T { + return anyToTSlice[T](a.Array.Rands(size)) +} + +// Shuffle randomly shuffles the array. +func (a *TArray[T]) Shuffle() *TArray[T] { + a.Array.Shuffle() + return a +} + +// Reverse makes array with elements in reverse order. +func (a *TArray[T]) Reverse() *TArray[T] { + a.Array.Reverse() + return a +} + +// Join joins array elements with a string `glue`. +func (a *TArray[T]) Join(glue string) string { + return a.Array.Join(glue) +} + +// CountValues counts the number of occurrences of all values in the array. +func (a *TArray[T]) CountValues() (valueCnt map[T]int) { + valueCnt = map[T]int{} + for k, v := range a.Array.CountValues() { + k0, _ := k.(T) + valueCnt[k0] = v + } + return +} + +// Iterator is alias of IteratorAsc. +func (a *TArray[T]) Iterator(f func(k int, v T) bool) { + a.Array.Iterator(func(k int, v any) bool { + v0, _ := v.(T) + return f(k, v0) + }) +} + +// IteratorAsc iterates the array readonly in ascending order with given callback function `f`. +// If `f` returns true, then it continues iterating; or false to stop. +func (a *TArray[T]) IteratorAsc(f func(k int, v T) bool) { + a.Array.IteratorAsc(func(k int, v any) bool { + v0, _ := v.(T) + return f(k, v0) + }) +} + +// IteratorDesc iterates the array readonly in descending order with given callback function `f`. +// If `f` returns true, then it continues iterating; or false to stop. +func (a *TArray[T]) IteratorDesc(f func(k int, v T) bool) { + a.Array.IteratorDesc(func(k int, v any) bool { + v0, _ := v.(T) + return f(k, v0) + }) +} + +// String returns current array as a string, which implements like json.Marshal does. +func (a *TArray[T]) String() string { + if a == nil { + return "" + } + return a.Array.String() +} + +// MarshalJSON implements the interface MarshalJSON for json.Marshal. +// Note that do not use pointer as its receiver here. +func (a TArray[T]) MarshalJSON() ([]byte, error) { + return a.Array.MarshalJSON() +} + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func (a *TArray[T]) UnmarshalJSON(b []byte) error { + return a.Array.UnmarshalJSON(b) +} + +// UnmarshalValue is an interface implement which sets any type of value for array. +func (a *TArray[T]) UnmarshalValue(value any) error { + return a.Array.UnmarshalValue(value) +} + +// Filter iterates array and filters elements using custom callback function. +// It removes the element from array if callback function `filter` returns true, +// it or else does nothing and continues iterating. +func (a *TArray[T]) Filter(filter func(index int, value T) bool) *TArray[T] { + a.Array.Filter(func(index int, value any) bool { + val, _ := value.(T) + return filter(index, val) + }) + return a +} + +// FilterNil removes all nil value of the array. +func (a *TArray[T]) FilterNil() *TArray[T] { + a.Array.FilterNil() + return a +} + +// FilterEmpty removes all empty value of the array. +// Values like: 0, nil, false, "", len(slice/map/chan) == 0 are considered empty. +func (a *TArray[T]) FilterEmpty() *TArray[T] { + a.Array.FilterEmpty() + return a +} + +// Walk applies a user supplied function `f` to every item of array. +func (a *TArray[T]) Walk(f func(value T) T) *TArray[T] { + a.Array.Walk(func(value any) any { + val, _ := value.(T) + return f(val) + }) + return a +} + +// IsEmpty checks whether the array is empty. +func (a *TArray[T]) IsEmpty() bool { + return a.Array.IsEmpty() +} + +// DeepCopy implements interface for deep copy of current type. +func (a *TArray[T]) DeepCopy() any { + if a == nil { + return nil + } + arr := a.Array.DeepCopy().(*Array) + return &TArray[T]{ + Array: *arr, + } +} diff --git a/container/garray/garray_z_example_normal_t_test.go b/container/garray/garray_z_example_normal_t_test.go new file mode 100644 index 000000000..152935fe0 --- /dev/null +++ b/container/garray/garray_z_example_normal_t_test.go @@ -0,0 +1,1281 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package garray_test + +import ( + "fmt" + "strings" + + "github.com/gogf/gf/v2/container/garray" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/internal/empty" + "github.com/gogf/gf/v2/internal/json" + "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" +) + +func ExampleTArray_Walk() { + { + var intArray garray.TArray[int] + intTables := g.SliceInt{10, 20} + intPrefix := 99 + intArray.Append(intTables...) + // Add prefix for given table names. + intArray.Walk(func(value int) int { + return intPrefix + value + }) + fmt.Println(intArray.Slice()) + } + + { + var strArray garray.TArray[string] + strTables := g.SliceStr{"user", "user_detail"} + strPrefix := "gf_" + strArray.Append(strTables...) + // Add prefix for given table names. + strArray.Walk(func(value string) string { + return strPrefix + value + }) + fmt.Println(strArray.Slice()) + } + + // Output: + // [109 119] + // [gf_user gf_user_detail] +} + +func ExampleNewTArray() { + { + intArr := garray.NewTArray[int]() + intArr.Append(10) + intArr.Append(20) + intArr.Append(15) + intArr.Append(30) + fmt.Println(intArr.Slice()) + } + + { + strArr := garray.NewTArray[string]() + strArr.Append("We") + strArr.Append("are") + strArr.Append("GF") + strArr.Append("fans") + fmt.Println(strArr.Slice()) + } + + // Output: + // [10 20 15 30] + // [We are GF fans] +} + +func ExampleNewTArraySize() { + { + intArr := garray.NewTArraySize[int](3, 5) + intArr.Set(0, 10) + intArr.Set(1, 20) + intArr.Set(2, 15) + intArr.Set(3, 30) + fmt.Println(intArr.Slice(), intArr.Len(), cap(intArr.Slice())) + } + + { + strArr := garray.NewTArraySize[string](3, 5) + strArr.Set(0, "We") + strArr.Set(1, "are") + strArr.Set(2, "GF") + strArr.Set(3, "fans") + fmt.Println(strArr.Slice(), strArr.Len(), cap(strArr.Slice())) + } + + // Output: + // [10 20 15] 3 5 + // [We are GF] 3 5 +} + +func ExampleNewTArrayFrom() { + { + intArr := garray.NewTArrayFrom[int](g.SliceInt{10, 20, 15, 30}) + fmt.Println(intArr.Slice(), intArr.Len(), cap(intArr.Slice())) + } + + { + strArr := garray.NewTArrayFrom[string](g.SliceStr{"We", "are", "GF", "fans", "!"}) + fmt.Println(strArr.Slice(), strArr.Len(), cap(strArr.Slice())) + } + + // Output: + // [10 20 15 30] 4 4 + // [We are GF fans !] 5 5 +} + +func ExampleNewTArrayFromCopy() { + { + intArr := garray.NewTArrayFromCopy(g.SliceInt{10, 20, 15, 30}) + fmt.Println(intArr.Slice(), intArr.Len(), cap(intArr.Slice())) + } + + { + strArr := garray.NewTArrayFromCopy(g.SliceStr{"a", "b", "c", "d", "e"}) + fmt.Println(strArr.Slice(), strArr.Len(), cap(strArr.Slice())) + } + + // Output: + // [10 20 15 30] 4 4 + // [a b c d e] 5 5 +} + +func ExampleTArray_At() { + { + intArr := garray.NewTArrayFrom[int](g.SliceInt{10, 20, 15, 30}) + isAt := intArr.At(2) + fmt.Println(isAt) + } + + { + strArr := garray.NewTArrayFrom[string](g.SliceStr{"We", "are", "GF", "fans", "!"}) + ssAt := strArr.At(2) + fmt.Println(ssAt) + } + + // Output: + // 15 + // GF +} + +func ExampleTArray_Get() { + { + s := garray.NewTArrayFrom[int](g.SliceInt{10, 20, 15, 30}) + sGet, sBool := s.Get(3) + fmt.Println(sGet, sBool) + sGet, sBool = s.Get(99) + fmt.Println(sGet, sBool) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"We", "are", "GF", "fans", "!"}) + sGet, sBool := s.Get(3) + fmt.Println(sGet, sBool) + } + + // Output: + // 30 true + // 0 false + // fans true +} + +func ExampleTArray_Set() { + { + s := garray.NewTArraySize[int](3, 5) + s.Set(0, 10) + s.Set(1, 20) + s.Set(2, 15) + s.Set(3, 30) + fmt.Println(s.Slice()) + } + { + s := garray.NewTArraySize[string](3, 5) + s.Set(0, "We") + s.Set(1, "are") + s.Set(2, "GF") + s.Set(3, "fans") + fmt.Println(s.Slice()) + } + + // Output: + // [10 20 15] + // [We are GF] +} + +func ExampleTArray_SetArray() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s.Slice()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"We", "are", "GF", "fans", "!"}) + fmt.Println(s.Slice()) + } + + // Output: + // [10 20 15 30] + // [We are GF fans !] +} + +func ExampleTArray_Replace() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s.Slice()) + s.Replace(g.SliceInt{12, 13}) + fmt.Println(s.Slice()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"We", "are", "GF", "fans", "!"}) + fmt.Println(s.Slice()) + s.Replace(g.SliceStr{"Happy", "coding"}) + fmt.Println(s.Slice()) + } + + // Output: + // [10 20 15 30] + // [12 13 15 30] + // [We are GF fans !] + // [Happy coding GF fans !] +} + +func ExampleTArray_Sum() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + a := s.Sum() + fmt.Println(a) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"3", "5", "10"}) + a := s.Sum() + fmt.Println(a) + } + // Output: + // 75 + // 18 +} + +func ExampleTArray_SortFunc() { + { + s := garray.NewTArrayFrom[int](g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.SortFunc(func(v1, v2 int) bool { + // fmt.Println(v1,v2) + return v1 > v2 + }) + fmt.Println(s) + s.SortFunc(func(v1, v2 int) bool { + return v1 < v2 + }) + fmt.Println(s) + } + + { + s := garray.NewTArrayFrom[string](g.SliceStr{"b", "c", "a"}) + fmt.Println(s) + s.SortFunc(func(v1, v2 string) bool { + return gstr.Compare(v1, v2) > 0 + }) + fmt.Println(s) + s.SortFunc(func(v1, v2 string) bool { + return gstr.Compare(v1, v2) < 0 + }) + fmt.Println(s) + } + + // Output: + // [10,20,15,30] + // [30,20,15,10] + // [10,15,20,30] + // ["b","c","a"] + // ["c","b","a"] + // ["a","b","c"] +} + +func ExampleTArray_InsertBefore() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + s.InsertBefore(1, 99) + fmt.Println(s.Slice()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.InsertBefore(1, "here") + fmt.Println(s.Slice()) + } + + // Output: + // [10 99 20 15 30] + // [a here b c d] +} + +func ExampleTArray_InsertAfter() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + s.InsertAfter(1, 99) + fmt.Println(s.Slice()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.InsertAfter(1, "here") + fmt.Println(s.Slice()) + } + // Output: + // [10 20 99 15 30] + // [a b here c d] +} + +func ExampleTArray_Remove() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.Remove(1) + fmt.Println(s.Slice()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.Remove(1) + fmt.Println(s.Slice()) + } + // Output: + // [10,20,15,30] + // [10 15 30] + // [a c d] +} + +func ExampleTArray_RemoveValue() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.RemoveValue(20) + fmt.Println(s.Slice()) + } + + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.RemoveValue("b") + fmt.Println(s.Slice()) + } + + // Output: + // [10,20,15,30] + // [10 15 30] + // [a c d] +} + +func ExampleTArray_PushLeft() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.PushLeft(96, 97, 98, 99) + fmt.Println(s.Slice()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.PushLeft("We", "are", "GF", "fans") + fmt.Println(s.Slice()) + } + + // Output: + // [10,20,15,30] + // [96 97 98 99 10 20 15 30] + // [We are GF fans a b c d] +} + +func ExampleTArray_PushRight() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.PushRight(96, 97, 98, 99) + fmt.Println(s.Slice()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.PushRight("We", "are", "GF", "fans") + fmt.Println(s.Slice()) + } + // Output: + // [10,20,15,30] + // [10 20 15 30 96 97 98 99] + // [a b c d We are GF fans] +} + +func ExampleTArray_PopLeft() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.PopLeft() + fmt.Println(s.Slice()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.PopLeft() + fmt.Println(s.Slice()) + } + // Output: + // [10,20,15,30] + // [20 15 30] + // [b c d] +} + +func ExampleTArray_PopRight() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30}) + fmt.Println(s) + s.PopRight() + fmt.Println(s.Slice()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d"}) + s.PopRight() + fmt.Println(s.Slice()) + } + // Output: + // [10,20,15,30] + // [10 20 15] + // [a b c] +} + +func ExampleTArray_PopRand() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60, 70}) + fmt.Println(s) + r, _ := s.PopRand() + fmt.Println(s) + fmt.Println(r) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r, _ := s.PopRand() + fmt.Println(r) + } + + // May Output: + // [10,20,15,30,40,50,60,70] + // [10,20,15,30,40,60,70] + // 50 + // e +} + +func ExampleTArray_PopRands() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.PopRands(2) + fmt.Println(s) + fmt.Println(r) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.PopRands(2) + fmt.Println(r) + } + // May Output: + // [10,20,15,30,40,50,60] + // [10,20,15,30,40] + // [50 60] + // [e c] +} + +func ExampleTArray_PopLefts() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.PopLefts(2) + fmt.Println(s) + fmt.Println(r) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.PopLefts(2) + fmt.Println(r) + fmt.Println(s) + } + // Output: + // [10,20,15,30,40,50,60] + // [15,30,40,50,60] + // [10 20] + // [a b] + // ["c","d","e","f","g","h"] +} + +func ExampleTArray_PopRights() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.PopRights(2) + fmt.Println(s) + fmt.Println(r) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.PopRights(2) + fmt.Println(r) + fmt.Println(s) + } + + // Output: + // [10,20,15,30,40,50,60] + // [10,20,15,30,40] + // [50 60] + // [g h] + // ["a","b","c","d","e","f"] +} + +func ExampleTArray_Range() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.Range(2, 5) + fmt.Println(r) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.Range(2, 5) + fmt.Println(r) + } + // Output: + // [10,20,15,30,40,50,60] + // [15 30 40] + // [c d e] +} + +func ExampleTArray_SubSlice() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.SubSlice(3, 4) + fmt.Println(r) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.SubSlice(3, 4) + fmt.Println(r) + } + // Output: + // [10,20,15,30,40,50,60] + // [30 40 50 60] + // [d e f g] +} + +func ExampleTArray_Append() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + s.Append(96, 97, 98) + fmt.Println(s) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"We", "are", "GF", "fans"}) + s.Append("a", "b", "c") + fmt.Println(s) + } + // Output: + // [10,20,15,30,40,50,60] + // [10,20,15,30,40,50,60,96,97,98] + // ["We","are","GF","fans","a","b","c"] +} + +func ExampleTArray_Len() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Len()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Len()) + } + // Output: + // [10,20,15,30,40,50,60] + // 7 + // 8 +} + +func ExampleTArray_Slice() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s.Slice()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Slice()) + } + // Output: + // [10 20 15 30 40 50 60] + // [a b c d e f g h] +} + +func ExampleTArray_Interfaces() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + r := s.Interfaces() + fmt.Println(r) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.Interfaces() + fmt.Println(r) + } + // Output: + // [10 20 15 30 40 50 60] + // [a b c d e f g h] +} + +func ExampleTArray_Clone() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.Clone() + fmt.Println(r) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.Clone() + fmt.Println(r) + fmt.Println(s) + } + // Output: + // [10,20,15,30,40,50,60] + // [10,20,15,30,40,50,60] + // ["a","b","c","d","e","f","g","h"] + // ["a","b","c","d","e","f","g","h"] +} + +func ExampleTArray_Clear() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Clear()) + fmt.Println(s) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s) + fmt.Println(s.Clear()) + fmt.Println(s) + } + // Output: + // [10,20,15,30,40,50,60] + // [] + // [] + // ["a","b","c","d","e","f","g","h"] + // [] + // [] +} + +func ExampleTArray_Contains() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s.Contains(20)) + fmt.Println(s.Contains(21)) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Contains("e")) + fmt.Println(s.Contains("z")) + } + // Output: + // true + // false + // true + // false +} + +func ExampleTArray_Search() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s.Search(20)) + fmt.Println(s.Search(21)) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Search("e")) + fmt.Println(s.Search("z")) + } + // Output: + // 1 + // -1 + // 4 + // -1 +} + +func ExampleTArray_Unique() { + { + s := garray.NewTArray[int]() + s.SetArray(g.SliceInt{10, 20, 15, 15, 20, 50, 60}) + fmt.Println(s) + fmt.Println(s.Unique()) + } + { + s := garray.NewTArray[string]() + s.SetArray(g.SliceStr{"a", "b", "c", "c", "c", "d", "d"}) + fmt.Println(s.Unique()) + } + // Output: + // [10,20,15,15,20,50,60] + // [10,20,15,50,60] + // ["a","b","c","d"] +} + +func ExampleTArray_LockFunc() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.LockFunc(func(array []int) { + for i := 0; i < len(array)-1; i++ { + fmt.Println(array[i]) + } + }) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c"}) + s.LockFunc(func(array []string) { + array[len(array)-1] = "GF fans" + }) + fmt.Println(s) + } + // Output: + // 10 + // 20 + // 15 + // 30 + // 40 + // 50 + // ["a","b","GF fans"] +} + +func ExampleTArray_RLockFunc() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.RLockFunc(func(array []int) { + for i := 0; i < len(array); i++ { + fmt.Println(array[i]) + } + }) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c", "d", "e"}) + s.RLockFunc(func(array []string) { + for i := 0; i < len(array); i++ { + fmt.Println(array[i]) + } + }) + } + // Output: + // 10 + // 20 + // 15 + // 30 + // 40 + // 50 + // 60 + // a + // b + // c + // d + // e +} + +func ExampleTArray_Merge() { + { + s1 := garray.NewTArray[int]() + s2 := garray.NewTArray[int]() + s1.SetArray(g.SliceInt{10, 20, 15}) + s2.SetArray(g.SliceInt{40, 50, 60}) + fmt.Println(s1) + fmt.Println(s2) + s1.Merge(s2) + fmt.Println(s1) + } + { + s1 := garray.NewTArray[string]() + s2 := garray.NewTArray[string]() + s1.SetArray(g.SliceStr{"a", "b", "c"}) + s2.SetArray(g.SliceStr{"d", "e", "f"}) + s1.Merge(s2) + fmt.Println(s1) + } + // Output: + // [10,20,15] + // [40,50,60] + // [10,20,15,40,50,60] + // ["a","b","c","d","e","f"] +} + +func ExampleTArray_Fill() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + s.Fill(2, 3, 99) + fmt.Println(s) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + s.Fill(2, 3, "here") + fmt.Println(s) + } + // Output: + // [10,20,15,30,40,50,60] + // [10,20,99,99,99,50,60] + // ["a","b","here","here","here","f","g","h"] +} + +func ExampleTArray_Chunk() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + r := s.Chunk(3) + fmt.Println(r) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + r := s.Chunk(3) + fmt.Println(r) + } + + // Output: + // [10,20,15,30,40,50,60] + // [[10 20 15] [30 40 50] [60]] + // [[a b c] [d e f] [g h]] +} + +func ExampleTArray_Pad() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.Pad(8, 99) + fmt.Println(s) + s.Pad(-10, 89) + fmt.Println(s) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c"}) + s.Pad(7, "here") + fmt.Println(s) + s.Pad(-10, "there") + fmt.Println(s) + } + + // Output: + // [10,20,15,30,40,50,60,99] + // [89,89,10,20,15,30,40,50,60,99] + // ["a","b","c","here","here","here","here"] + // ["there","there","there","a","b","c","here","here","here","here"] +} + +func ExampleTArray_Rand() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Rand()) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Rand()) + } + + // May Output: + // [10,20,15,30,40,50,60] + // 10 true + // c true +} + +func ExampleTArray_Rands() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Rands(3)) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Rands(3)) + } + + // May Output: + // [10,20,15,30,40,50,60] + // [20 50 20] + // [e h e] +} + +func ExampleTArray_Shuffle() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Shuffle()) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Shuffle()) + } + + // May Output: + // [10,20,15,30,40,50,60] + // [10,40,15,50,20,60,30] + // ["a","c","e","d","b","g","f","h"] +} + +func ExampleTArray_Reverse() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Reverse()) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c", "d", "e", "f", "g", "h"}) + fmt.Println(s.Reverse()) + } + + // Output: + // [10,20,15,30,40,50,60] + // [60,50,40,30,15,20,10] + // ["h","g","f","e","d","c","b","a"] +} + +func ExampleTArray_Join() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.Join(",")) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c"}) + fmt.Println(s.Join(",")) + } + + // Output: + // [10,20,15,30,40,50,60] + // 10,20,15,30,40,50,60 + // a,b,c +} + +func ExampleTArray_CountValues() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 15, 40, 40, 40}) + fmt.Println(s.CountValues()) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c", "c", "c", "d", "d"}) + fmt.Println(s.CountValues()) + } + + // Output: + // map[10:1 15:2 20:1 40:3] + // map[a:1 b:1 c:3 d:2] +} + +func ExampleTArray_Iterator() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.Iterator(func(k int, v int) bool { + fmt.Println(k, v) + return true + }) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c"}) + s.Iterator(func(k int, v string) bool { + fmt.Println(k, v) + return true + }) + } + + // Output: + // 0 10 + // 1 20 + // 2 15 + // 3 30 + // 4 40 + // 5 50 + // 6 60 + // 0 a + // 1 b + // 2 c +} + +func ExampleTArray_IteratorAsc() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.IteratorAsc(func(k int, v int) bool { + fmt.Println(k, v) + return true + }) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c"}) + s.IteratorAsc(func(k int, v string) bool { + fmt.Println(k, v) + return true + }) + } + + // Output: + // 0 10 + // 1 20 + // 2 15 + // 3 30 + // 4 40 + // 5 50 + // 6 60 + // 0 a + // 1 b + // 2 c +} + +func ExampleTArray_IteratorDesc() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + s.IteratorDesc(func(k int, v int) bool { + fmt.Println(k, v) + return true + }) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c"}) + s.IteratorDesc(func(k int, v string) bool { + fmt.Println(k, v) + return true + }) + } + + // Output: + // 6 60 + // 5 50 + // 4 40 + // 3 30 + // 2 15 + // 1 20 + // 0 10 + // 2 c + // 1 b + // 0 a +} + +func ExampleTArray_String() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s) + fmt.Println(s.String()) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "c"}) + fmt.Println(s.String()) + } + + // Output: + // [10,20,15,30,40,50,60] + // [10,20,15,30,40,50,60] + // ["a","b","c"] +} + +func ExampleTArray_MarshalJSON() { + { + type Student struct { + Id int + Name string + Scores garray.TArray[int] + } + var array garray.TArray[int] + array.SetArray(g.SliceInt{98, 97, 96}) + s := Student{ + Id: 1, + Name: "john", + Scores: array, + } + b, _ := json.Marshal(s) + fmt.Println(string(b)) + } + { + type Student struct { + Id int + Name string + Lessons []string + } + s := Student{ + Id: 1, + Name: "john", + Lessons: []string{"Math", "English", "Music"}, + } + b, _ := json.Marshal(s) + fmt.Println(string(b)) + } + + // Output: + // {"Id":1,"Name":"john","Scores":[98,97,96]} + // {"Id":1,"Name":"john","Lessons":["Math","English","Music"]} +} + +func ExampleTArray_UnmarshalJSON() { + { + b := []byte(`{"Id":1,"Name":"john","Scores":[98,96,97]}`) + type Student struct { + Id int + Name string + Scores *garray.TArray[int] + } + s := Student{} + json.Unmarshal(b, &s) + fmt.Println(s) + } + { + b := []byte(`{"Id":1,"Name":"john","Lessons":["Math","English","Sport"]}`) + type Student struct { + Id int + Name string + Lessons *garray.TArray[string] + } + s := Student{} + json.Unmarshal(b, &s) + fmt.Println(s) + } + + // Output: + // {1 john [98,96,97]} + // {1 john ["Math","English","Sport"]} +} + +func ExampleTArray_UnmarshalValue() { + { + type Student struct { + Name string + Scores *garray.TArray[int] + } + + var s *Student + gconv.Struct(g.Map{ + "name": "john", + "scores": g.SliceInt{96, 98, 97}, + }, &s) + fmt.Println(s) + } + { + type Student struct { + Name string + Lessons *garray.TArray[string] + } + var s *Student + gconv.Struct(g.Map{ + "name": "john", + "lessons": []byte(`["Math","English","Sport"]`), + }, &s) + fmt.Println(s) + + var s1 *Student + gconv.Struct(g.Map{ + "name": "john", + "lessons": g.SliceStr{"Math", "English", "Sport"}, + }, &s1) + fmt.Println(s1) + } + + // Output: + // &{john [96,98,97]} + // &{john ["Math","English","Sport"]} + // &{john ["Math","English","Sport"]} +} + +func ExampleTArray_Filter() { + { + array1 := garray.NewTArrayFrom(g.SliceInt{10, 40, 50, 0, 0, 0, 60}) + array2 := garray.NewTArrayFrom(g.SliceInt{10, 4, 51, 5, 45, 50, 56}) + fmt.Println(array1.Filter(func(index int, value int) bool { + return empty.IsEmpty(value) + })) + fmt.Println(array2.Filter(func(index int, value int) bool { + return value%2 == 0 + })) + fmt.Println(array2.Filter(func(index int, value int) bool { + return value%2 == 1 + })) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"Math", "English", "Sport"}) + s1 := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "", "c", "", "", "d"}) + fmt.Println(s1.Filter(func(index int, value string) bool { + return empty.IsEmpty(value) + })) + + fmt.Println(s.Filter(func(index int, value string) bool { + return strings.Contains(value, "h") + })) + } + + // Output: + // [10,40,50,60] + // [51,5,45] + // [] + // ["a","b","c","d"] + // ["Sport"] +} + +func ExampleTArray_FilterEmpty() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 40, 50, 0, 0, 0, 60}) + fmt.Println(s) + fmt.Println(s.FilterEmpty()) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "", "c", "", "", "d"}) + fmt.Println(s.FilterEmpty()) + } + + // Output: + // [10,40,50,0,0,0,60] + // [10,40,50,60] + // ["a","b","c","d"] +} + +func ExampleTArray_IsEmpty() { + { + s := garray.NewTArrayFrom(g.SliceInt{10, 20, 15, 30, 40, 50, 60}) + fmt.Println(s.IsEmpty()) + s1 := garray.NewTArray[int]() + fmt.Println(s1.IsEmpty()) + } + { + s := garray.NewTArrayFrom[string](g.SliceStr{"a", "b", "", "c", "", "", "d"}) + fmt.Println(s.IsEmpty()) + s1 := garray.NewTArray[string]() + fmt.Println(s1.IsEmpty()) + } + + // Output: + // false + // true + // false + // true +} diff --git a/container/garray/garray_z_unit_normal_t_test.go b/container/garray/garray_z_unit_normal_t_test.go new file mode 100644 index 000000000..e3dbeb2a3 --- /dev/null +++ b/container/garray/garray_z_unit_normal_t_test.go @@ -0,0 +1,851 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// go test *.go + +package garray_test + +import ( + "testing" + "time" + + "github.com/gogf/gf/v2/container/garray" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/internal/empty" + "github.com/gogf/gf/v2/internal/json" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/gconv" +) + +func Test_TArray_Basic(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + expect := []int{0, 1, 2, 3} + array := garray.NewTArrayFrom(expect) + array2 := garray.NewTArrayFrom(expect) + array3 := garray.NewTArrayFrom([]int{}) + + t.Assert(array.Slice(), expect) + t.Assert(array.Interfaces(), expect) + err := array.Set(0, 100) // 100, 1, 2, 3 + t.AssertNil(err) + + err = array.Set(100, 100) + t.AssertNE(err, nil) + + t.Assert(array.IsEmpty(), false) + + copyArray := array.DeepCopy() + ca := copyArray.(*garray.TArray[int]) + ca.Set(0, 1) + cval, _ := ca.Get(0) + val, _ := array.Get(0) + t.AssertNE(cval, val) + + v, ok := array.Get(0) + t.Assert(v, 100) + t.Assert(ok, true) + + v, ok = array.Get(1) + t.Assert(v, 1) + t.Assert(ok, true) + + v, ok = array.Get(4) + t.Assert(v, 0) + t.Assert(ok, false) + + t.Assert(array.Search(100), 0) + t.Assert(array3.Search(100), -1) + t.Assert(array.Contains(100), true) + + v, ok = array.Remove(0) // 1, 2, 3 + t.Assert(v, 100) + t.Assert(ok, true) + + v, ok = array.Remove(-1) + t.Assert(v, 0) + t.Assert(ok, false) + + v, ok = array.Remove(100000) + t.Assert(v, 0) + t.Assert(ok, false) + + v, ok = array2.Remove(3) // 0 1 2 + t.Assert(v, 3) + t.Assert(ok, true) + + v, ok = array2.Remove(1) // 0 2 + t.Assert(v, 1) + t.Assert(ok, true) + + t.Assert(array.Contains(100), false) + array.Append(4) // 1, 2, 3 ,4 + t.Assert(array.Len(), 4) + array.InsertBefore(0, 100) // 100, 1, 2, 3, 4 + array.InsertAfter(0, 200) // 100, 200, 1, 2, 3, 4 + t.Assert(array.Slice(), []int{100, 200, 1, 2, 3, 4}) + array.InsertBefore(5, 300) + array.InsertAfter(6, 400) + t.Assert(array.Slice(), []int{100, 200, 1, 2, 3, 300, 4, 400}) + t.Assert(array.Clear().Len(), 0) + err = array.InsertBefore(99, 9900) + t.AssertNE(err, nil) + err = array.InsertAfter(99, 9900) + t.AssertNE(err, nil) + + t.Assert(array.String(), "[]") + }) +} + +func TestTArray_Sort(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + expect1 := []any{0, 1, 2, 3} + expect2 := []any{3, 2, 1, 0} + array := garray.NewTArray[int]() + for i := 3; i >= 0; i-- { + array.Append(i) + } + array.SortFunc(func(v1, v2 int) bool { + return v1 < v2 + }) + t.Assert(array.Slice(), expect1) + array.SortFunc(func(v1, v2 int) bool { + return v1 > v2 + }) + t.Assert(array.Slice(), expect2) + }) +} + +func TestTArray_Unique(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + expect := []int{1, 2, 3, 4, 5, 3, 2, 2, 3, 5, 5} + array := garray.NewTArrayFrom(expect) + t.Assert(array.Unique().Slice(), []int{1, 2, 3, 4, 5}) + }) + gtest.C(t, func(t *gtest.T) { + expect := []int{} + array := garray.NewTArrayFrom(expect) + t.Assert(array.Unique().Slice(), []int{}) + }) +} + +func TestTArray_PushAndPop(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + expect := []any{0, 1, 2, 3} + array := garray.NewTArrayFrom(expect) + t.Assert(array.Slice(), expect) + + v, ok := array.PopLeft() + t.Assert(v, 0) + t.Assert(ok, true) + + v, ok = array.PopRight() + t.Assert(v, 3) + t.Assert(ok, true) + + v, ok = array.PopRand() + t.AssertIN(v, []any{1, 2}) + t.Assert(ok, true) + + v, ok = array.PopRand() + t.AssertIN(v, []any{1, 2}) + t.Assert(ok, true) + + t.Assert(array.Len(), 0) + array.PushLeft(1).PushRight(2) + t.Assert(array.Slice(), []any{1, 2}) + }) +} + +func TestTArray_PopRands(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{100, 200, 300, 400, 500, 600} + array := garray.NewFromCopy(a1) + t.AssertIN(array.PopRands(2), []any{100, 200, 300, 400, 500, 600}) + }) +} + +func TestTArray_PopLeft(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + array := garray.NewFrom(g.Slice{1, 2, 3}) + v, ok := array.PopLeft() + t.Assert(v, 1) + t.Assert(ok, true) + t.Assert(array.Len(), 2) + v, ok = array.PopLeft() + t.Assert(v, 2) + t.Assert(ok, true) + t.Assert(array.Len(), 1) + v, ok = array.PopLeft() + t.Assert(v, 3) + t.Assert(ok, true) + t.Assert(array.Len(), 0) + }) +} + +func TestTArray_PopRight(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + array := garray.NewFrom(g.Slice{1, 2, 3}) + + v, ok := array.PopRight() + t.Assert(v, 3) + t.Assert(ok, true) + t.Assert(array.Len(), 2) + + v, ok = array.PopRight() + t.Assert(v, 2) + t.Assert(ok, true) + t.Assert(array.Len(), 1) + + v, ok = array.PopRight() + t.Assert(v, 1) + t.Assert(ok, true) + t.Assert(array.Len(), 0) + }) +} + +func TestTArray_PopLefts(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + array := garray.NewFrom(g.Slice{1, 2, 3}) + t.Assert(array.PopLefts(2), g.Slice{1, 2}) + t.Assert(array.Len(), 1) + t.Assert(array.PopLefts(2), g.Slice{3}) + t.Assert(array.Len(), 0) + }) +} + +func TestTArray_PopRights(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + array := garray.NewFrom(g.Slice{1, 2, 3}) + t.Assert(array.PopRights(2), g.Slice{2, 3}) + t.Assert(array.Len(), 1) + t.Assert(array.PopLefts(2), g.Slice{1}) + t.Assert(array.Len(), 0) + }) +} + +func TestTArray_PopLeftsAndPopRights(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + array := garray.New() + v, ok := array.PopLeft() + t.Assert(v, nil) + t.Assert(ok, false) + t.Assert(array.PopLefts(10), nil) + + v, ok = array.PopRight() + t.Assert(v, nil) + t.Assert(ok, false) + t.Assert(array.PopRights(10), nil) + + v, ok = array.PopRand() + t.Assert(v, nil) + t.Assert(ok, false) + t.Assert(array.PopRands(10), nil) + }) + + gtest.C(t, func(t *gtest.T) { + value1 := []any{0, 1, 2, 3, 4, 5, 6} + value2 := []any{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewTArrayFrom(value1) + array2 := garray.NewTArrayFrom(value2) + t.Assert(array1.PopLefts(2), []any{0, 1}) + t.Assert(array1.Slice(), []any{2, 3, 4, 5, 6}) + t.Assert(array1.PopRights(2), []any{5, 6}) + t.Assert(array1.Slice(), []any{2, 3, 4}) + t.Assert(array1.PopRights(20), []any{2, 3, 4}) + t.Assert(array1.Slice(), []any{}) + t.Assert(array2.PopLefts(20), []any{0, 1, 2, 3, 4, 5, 6}) + t.Assert(array2.Slice(), []any{}) + }) +} + +func TestTArray_Range(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + value1 := []any{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewTArrayFrom(value1) + array2 := garray.NewTArrayFrom(value1, true) + t.Assert(array1.Range(0, 1), []any{0}) + t.Assert(array1.Range(1, 2), []any{1}) + t.Assert(array1.Range(0, 2), []any{0, 1}) + t.Assert(array1.Range(-1, 10), value1) + t.Assert(array1.Range(10, 2), nil) + t.Assert(array2.Range(1, 3), []any{1, 2}) + }) +} + +func TestTArray_Merge(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + func1 := func(v1, v2 any) int { + if gconv.Int(v1) < gconv.Int(v2) { + return 0 + } + return 1 + } + + i1 := []any{0, 1, 2, 3} + i2 := []any{4, 5, 6, 7} + array1 := garray.NewTArrayFrom(i1) + array2 := garray.NewTArrayFrom(i2) + t.Assert(array1.Merge(array2).Slice(), []any{0, 1, 2, 3, 4, 5, 6, 7}) + + // s1 := []string{"a", "b", "c", "d"} + s2 := []string{"e", "f"} + i3 := garray.NewIntArrayFrom([]int{1, 2, 3}) + i4 := garray.NewTArrayFrom([]any{3}) + s3 := garray.NewStrArrayFrom([]string{"g", "h"}) + s4 := garray.NewSortedArrayFrom([]any{4, 5}, func1) + s5 := garray.NewSortedStrArrayFrom(s2) + s6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3}) + a1 := garray.NewTArrayFrom(i1) + + t.Assert(a1.Merge(s2).Len(), 6) + t.Assert(a1.Merge(i3).Len(), 9) + t.Assert(a1.Merge(i4).Len(), 10) + t.Assert(a1.Merge(s3).Len(), 12) + t.Assert(a1.Merge(s4).Len(), 14) + t.Assert(a1.Merge(s5).Len(), 16) + t.Assert(a1.Merge(s6).Len(), 19) + }) +} + +func TestTArray_Fill(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0} + a2 := []any{0} + array1 := garray.NewTArrayFrom(a1) + array2 := garray.NewTArrayFrom(a2, true) + + t.Assert(array1.Fill(1, 2, 100), nil) + t.Assert(array1.Slice(), []any{0, 100, 100}) + + t.Assert(array2.Fill(0, 2, 100), nil) + t.Assert(array2.Slice(), []any{100, 100}) + + t.AssertNE(array2.Fill(-1, 2, 100), nil) + t.Assert(array2.Slice(), []any{100, 100}) + }) +} + +func TestTArray_Chunk(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{1, 2, 3, 4, 5} + array1 := garray.NewTArrayFrom(a1) + chunks := array1.Chunk(2) + t.Assert(len(chunks), 3) + t.Assert(chunks[0], []any{1, 2}) + t.Assert(chunks[1], []any{3, 4}) + t.Assert(chunks[2], []any{5}) + t.Assert(array1.Chunk(0), nil) + }) + gtest.C(t, func(t *gtest.T) { + a1 := []any{1, 2, 3, 4, 5} + array1 := garray.NewTArrayFrom(a1) + chunks := array1.Chunk(3) + t.Assert(len(chunks), 2) + t.Assert(chunks[0], []any{1, 2, 3}) + t.Assert(chunks[1], []any{4, 5}) + t.Assert(array1.Chunk(0), nil) + }) + gtest.C(t, func(t *gtest.T) { + a1 := []any{1, 2, 3, 4, 5, 6} + array1 := garray.NewTArrayFrom(a1) + chunks := array1.Chunk(2) + t.Assert(len(chunks), 3) + t.Assert(chunks[0], []any{1, 2}) + t.Assert(chunks[1], []any{3, 4}) + t.Assert(chunks[2], []any{5, 6}) + t.Assert(array1.Chunk(0), nil) + }) + gtest.C(t, func(t *gtest.T) { + a1 := []any{1, 2, 3, 4, 5, 6} + array1 := garray.NewTArrayFrom(a1) + chunks := array1.Chunk(3) + t.Assert(len(chunks), 2) + t.Assert(chunks[0], []any{1, 2, 3}) + t.Assert(chunks[1], []any{4, 5, 6}) + t.Assert(array1.Chunk(0), nil) + }) +} + +func TestTArray_Pad(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0} + array1 := garray.NewTArrayFrom(a1) + t.Assert(array1.Pad(3, 1).Slice(), []any{0, 1, 1}) + t.Assert(array1.Pad(-4, 1).Slice(), []any{1, 0, 1, 1}) + t.Assert(array1.Pad(3, 1).Slice(), []any{1, 0, 1, 1}) + }) +} + +func TestTArray_SubSlice(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewTArrayFrom(a1) + array2 := garray.NewTArrayFrom(a1, true) + t.Assert(array1.SubSlice(0, 2), []any{0, 1}) + t.Assert(array1.SubSlice(2, 2), []any{2, 3}) + t.Assert(array1.SubSlice(5, 8), []any{5, 6}) + t.Assert(array1.SubSlice(9, 1), nil) + t.Assert(array1.SubSlice(-2, 2), []any{5, 6}) + t.Assert(array1.SubSlice(-9, 2), nil) + t.Assert(array1.SubSlice(1, -2), nil) + t.Assert(array2.SubSlice(0, 2), []any{0, 1}) + }) +} + +func TestTArray_Rand(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewTArrayFrom(a1) + t.Assert(len(array1.Rands(2)), 2) + t.Assert(len(array1.Rands(10)), 10) + t.AssertIN(array1.Rands(1)[0], a1) + }) + + gtest.C(t, func(t *gtest.T) { + s1 := []any{"a", "b", "c", "d"} + a1 := garray.NewTArrayFrom(s1) + i1, ok := a1.Rand() + t.Assert(ok, true) + t.Assert(a1.Contains(i1), true) + t.Assert(a1.Len(), 4) + }) + + gtest.C(t, func(t *gtest.T) { + a1 := []any{} + array1 := garray.NewTArrayFrom(a1) + rand, found := array1.Rand() + t.AssertNil(rand) + t.Assert(found, false) + }) + + gtest.C(t, func(t *gtest.T) { + a1 := []any{} + array1 := garray.NewTArrayFrom(a1) + rand := array1.Rands(1) + t.AssertNil(rand) + }) +} + +func TestTArray_Shuffle(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewTArrayFrom(a1) + t.Assert(array1.Shuffle().Len(), 7) + }) +} + +func TestTArray_Reverse(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewTArrayFrom(a1) + t.Assert(array1.Reverse().Slice(), []any{6, 5, 4, 3, 2, 1, 0}) + }) +} + +func TestTArray_Join(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewTArrayFrom(a1) + t.Assert(array1.Join("."), `0.1.2.3.4.5.6`) + }) + + gtest.C(t, func(t *gtest.T) { + a1 := []any{0, 1, `"a"`, `\a`} + array1 := garray.NewTArrayFrom(a1) + t.Assert(array1.Join("."), `0.1."a".\a`) + }) + + gtest.C(t, func(t *gtest.T) { + a1 := []any{} + array1 := garray.NewTArrayFrom(a1) + t.Assert(len(array1.Join(".")), 0) + }) +} + +func TestTArray_String(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0, 1, 2, 3, 4, 5, 6} + array1 := garray.NewTArrayFrom(a1) + t.Assert(array1.String(), `[0,1,2,3,4,5,6]`) + array1 = nil + t.Assert(array1.String(), "") + }) +} + +func TestTArray_Replace(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0, 1, 2, 3, 4, 5, 6} + a2 := []any{"a", "b", "c"} + a3 := []any{"m", "n", "p", "z", "x", "y", "d", "u"} + array1 := garray.NewTArrayFrom(a1) + array2 := array1.Replace(a2) + t.Assert(array2.Len(), 7) + t.Assert(array2.Contains("b"), true) + t.Assert(array2.Contains(4), true) + t.Assert(array2.Contains("v"), false) + array3 := array1.Replace(a3) + t.Assert(array3.Len(), 7) + t.Assert(array3.Contains(4), false) + t.Assert(array3.Contains("p"), true) + t.Assert(array3.Contains("u"), false) + }) +} + +func TestTArray_SetArray(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0, 1, 2, 3, 4, 5, 6} + a2 := []any{"a", "b", "c"} + + array1 := garray.NewTArrayFrom(a1) + array1 = array1.SetArray(a2) + t.Assert(array1.Len(), 3) + t.Assert(array1.Contains("b"), true) + t.Assert(array1.Contains("5"), false) + }) +} + +func TestTArray_Sum(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0, 1, 2, 3} + a2 := []any{"a", "b", "c"} + a3 := []any{"a", "1", "2"} + + array1 := garray.NewTArrayFrom(a1) + array2 := garray.NewTArrayFrom(a2) + array3 := garray.NewTArrayFrom(a3) + + t.Assert(array1.Sum(), 6) + t.Assert(array2.Sum(), 0) + t.Assert(array3.Sum(), 3) + + }) +} + +func TestTArray_Clone(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{0, 1, 2, 3} + array1 := garray.NewTArrayFrom(a1) + array2 := array1.Clone() + + t.Assert(array1.Len(), 4) + t.Assert(array2.Sum(), 6) + t.AssertEQ(array1, array2) + + }) +} + +func TestTArray_CountValues(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + a1 := []any{"a", "b", "c", "d", "e", "d"} + array1 := garray.NewTArrayFrom(a1) + array2 := array1.CountValues() + t.Assert(len(array2), 5) + t.Assert(array2["b"], 1) + t.Assert(array2["d"], 2) + }) +} + +func TestTArray_LockFunc(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + s1 := []any{"a", "b", "c", "d"} + a1 := garray.NewTArrayFrom(s1, true) + + ch1 := make(chan int64, 3) + ch2 := make(chan int64, 3) + // go1 + go a1.LockFunc(func(n1 []any) { // 读写锁 + time.Sleep(2 * time.Second) // 暂停2秒 + n1[2] = "g" + ch2 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }) + + // go2 + go func() { + time.Sleep(100 * time.Millisecond) // 故意暂停0.01秒,等go1执行锁后,再开始执行. + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + a1.Len() + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }() + + t1 := <-ch1 + t2 := <-ch1 + <-ch2 // 等待go1完成 + + // 防止ci抖动,以豪秒为单位 + t.AssertGT(t2-t1, 20) // go1加的读写互斥锁,所go2读的时候被阻塞。 + t.Assert(a1.Contains("g"), true) + }) +} + +func TestTArray_RLockFunc(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + s1 := []any{"a", "b", "c", "d"} + a1 := garray.NewTArrayFrom(s1, true) + + ch1 := make(chan int64, 3) + ch2 := make(chan int64, 1) + // go1 + go a1.RLockFunc(func(n1 []any) { // 读锁 + time.Sleep(2 * time.Second) // 暂停1秒 + n1[2] = "g" + ch2 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }) + + // go2 + go func() { + time.Sleep(100 * time.Millisecond) // 故意暂停0.01秒,等go1执行锁后,再开始执行. + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + a1.Len() + ch1 <- gconv.Int64(time.Now().UnixNano() / 1000 / 1000) + }() + + t1 := <-ch1 + t2 := <-ch1 + <-ch2 // 等待go1完成 + + // 防止ci抖动,以豪秒为单位 + t.AssertLT(t2-t1, 20) // go1加的读锁,所go2读的时候,并没有阻塞。 + t.Assert(a1.Contains("g"), false) + }) +} + +func TestTArray_Json(t *testing.T) { + // pointer + gtest.C(t, func(t *gtest.T) { + s1 := []any{"a", "b", "d", "c"} + a1 := garray.NewTArrayFrom(s1) + b1, err1 := json.Marshal(a1) + b2, err2 := json.Marshal(s1) + t.Assert(b1, b2) + t.Assert(err1, err2) + + a2 := garray.New() + err2 = json.UnmarshalUseNumber(b2, &a2) + t.Assert(err2, nil) + t.Assert(a2.Slice(), s1) + + var a3 garray.Array + err := json.UnmarshalUseNumber(b2, &a3) + t.AssertNil(err) + t.Assert(a3.Slice(), s1) + }) + // value. + gtest.C(t, func(t *gtest.T) { + s1 := []any{"a", "b", "d", "c"} + a1 := *garray.NewTArrayFrom(s1) + b1, err1 := json.Marshal(a1) + b2, err2 := json.Marshal(s1) + t.Assert(b1, b2) + t.Assert(err1, err2) + + a2 := garray.New() + err2 = json.UnmarshalUseNumber(b2, &a2) + t.Assert(err2, nil) + t.Assert(a2.Slice(), s1) + + var a3 garray.Array + err := json.UnmarshalUseNumber(b2, &a3) + t.AssertNil(err) + t.Assert(a3.Slice(), s1) + }) + // pointer + gtest.C(t, func(t *gtest.T) { + type User struct { + Name string + Scores *garray.Array + } + data := g.Map{ + "Name": "john", + "Scores": []int{99, 100, 98}, + } + b, err := json.Marshal(data) + t.AssertNil(err) + + user := new(User) + err = json.UnmarshalUseNumber(b, user) + t.AssertNil(err) + t.Assert(user.Name, data["Name"]) + t.Assert(user.Scores, data["Scores"]) + }) + // value + gtest.C(t, func(t *gtest.T) { + type User struct { + Name string + Scores garray.Array + } + data := g.Map{ + "Name": "john", + "Scores": []int{99, 100, 98}, + } + b, err := json.Marshal(data) + t.AssertNil(err) + + user := new(User) + err = json.UnmarshalUseNumber(b, user) + t.AssertNil(err) + t.Assert(user.Name, data["Name"]) + t.Assert(user.Scores, data["Scores"]) + }) +} + +func TestTArray_Iterator(t *testing.T) { + slice := g.Slice{"a", "b", "d", "c"} + array := garray.NewTArrayFrom(slice) + gtest.C(t, func(t *gtest.T) { + array.Iterator(func(k int, v any) bool { + t.Assert(v, slice[k]) + return true + }) + }) + gtest.C(t, func(t *gtest.T) { + array.IteratorAsc(func(k int, v any) bool { + t.Assert(v, slice[k]) + return true + }) + }) + gtest.C(t, func(t *gtest.T) { + array.IteratorDesc(func(k int, v any) bool { + t.Assert(v, slice[k]) + return true + }) + }) + gtest.C(t, func(t *gtest.T) { + index := 0 + array.Iterator(func(k int, v any) bool { + index++ + return false + }) + t.Assert(index, 1) + }) + gtest.C(t, func(t *gtest.T) { + index := 0 + array.IteratorAsc(func(k int, v any) bool { + index++ + return false + }) + t.Assert(index, 1) + }) + gtest.C(t, func(t *gtest.T) { + index := 0 + array.IteratorDesc(func(k int, v any) bool { + index++ + return false + }) + t.Assert(index, 1) + }) +} + +func TestTArray_RemoveValue(t *testing.T) { + slice := g.Slice{"a", "b", "d", "c"} + array := garray.NewTArrayFrom(slice) + gtest.C(t, func(t *gtest.T) { + t.Assert(array.RemoveValue("e"), false) + t.Assert(array.RemoveValue("b"), true) + t.Assert(array.RemoveValue("a"), true) + t.Assert(array.RemoveValue("c"), true) + t.Assert(array.RemoveValue("f"), false) + }) +} + +func TestTArray_RemoveValues(t *testing.T) { + slice := g.SliceStr{"a", "b", "d", "c"} + array := garray.NewTArrayFrom(slice) + gtest.C(t, func(t *gtest.T) { + array.RemoveValues("a", "b", "c") + t.Assert(array.Slice(), g.Slice{"d"}) + }) +} + +func TestTArray_UnmarshalValue(t *testing.T) { + type V struct { + Name string + Array *garray.Array + } + // JSON + gtest.C(t, func(t *gtest.T) { + var v *V + err := gconv.Struct(g.Map{ + "name": "john", + "array": []byte(`[1,2,3]`), + }, &v) + t.AssertNil(err) + t.Assert(v.Name, "john") + t.Assert(v.Array.Slice(), g.Slice{1, 2, 3}) + }) + // Map + gtest.C(t, func(t *gtest.T) { + var v *V + err := gconv.Struct(g.Map{ + "name": "john", + "array": g.Slice{1, 2, 3}, + }, &v) + t.AssertNil(err) + t.Assert(v.Name, "john") + t.Assert(v.Array.Slice(), g.Slice{1, 2, 3}) + }) +} + +func TestTArray_FilterNil(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + values := g.Slice{0, 1, 2, 3, 4, "", g.Slice{}} + array := garray.NewTArrayFromCopy(values) + t.Assert(array.FilterNil().Slice(), values) + }) + gtest.C(t, func(t *gtest.T) { + array := garray.NewTArrayFromCopy(g.Slice{nil, 1, 2, 3, 4, nil}) + t.Assert(array.FilterNil(), g.Slice{1, 2, 3, 4}) + }) +} + +func TestTArray_Filter(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + values := g.Slice{0, 1, 2, 3, 4, "", g.Slice{}} + array := garray.NewTArrayFromCopy(values) + t.Assert(array.Filter(func(index int, value any) bool { + return empty.IsNil(value) + }).Slice(), values) + }) + gtest.C(t, func(t *gtest.T) { + array := garray.NewTArrayFromCopy(g.Slice{nil, 1, 2, 3, 4, nil}) + t.Assert(array.Filter(func(index int, value any) bool { + return empty.IsNil(value) + }), g.Slice{1, 2, 3, 4}) + }) + gtest.C(t, func(t *gtest.T) { + array := garray.NewTArrayFrom(g.Slice{0, 1, 2, 3, 4, "", g.Slice{}}) + + t.Assert(array.Filter(func(index int, value any) bool { + return empty.IsEmpty(value) + }), g.Slice{1, 2, 3, 4}) + }) + gtest.C(t, func(t *gtest.T) { + array := garray.NewTArrayFrom(g.Slice{1, 2, 3, 4}) + + t.Assert(array.Filter(func(index int, value any) bool { + return empty.IsEmpty(value) + }), g.Slice{1, 2, 3, 4}) + }) +} + +func TestTArray_FilterEmpty(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + array := garray.NewTArrayFrom(g.Slice{0, 1, 2, 3, 4, "", g.Slice{}}) + t.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4}) + }) + gtest.C(t, func(t *gtest.T) { + array := garray.NewTArrayFrom(g.Slice{1, 2, 3, 4}) + t.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4}) + }) +} + +func TestTArray_Walk(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + array := garray.NewTArrayFrom(g.Slice{"1", "2"}) + t.Assert(array.Walk(func(value any) any { + return "key-" + gconv.String(value) + }), g.Slice{"key-1", "key-2"}) + }) +}