mirror of
https://gitee.com/johng/gf
synced 2026-07-04 21:03:13 +08:00
feat(container/garray): add TArray (#4466)
Add TArray[T] for wrapping Array --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@ -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
|
||||
}
|
||||
|
||||
493
container/garray/garray_normal_t.go
Normal file
493
container/garray/garray_normal_t.go
Normal file
@ -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,
|
||||
}
|
||||
}
|
||||
1281
container/garray/garray_z_example_normal_t_test.go
Normal file
1281
container/garray/garray_z_example_normal_t_test.go
Normal file
File diff suppressed because it is too large
Load Diff
851
container/garray/garray_z_unit_normal_t_test.go
Normal file
851
container/garray/garray_z_unit_normal_t_test.go
Normal file
@ -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"})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user