Skip to content

Commit

Permalink
✨ feat: arrutil - enhance the Ints and Strings and SortedList
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Jul 5, 2023
1 parent 7747e31 commit fe184cf
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 55 deletions.
109 changes: 84 additions & 25 deletions arrutil/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import (
)

// Ints type
type Ints []int
type Ints[T comdef.Integer] []T

// String to string
func (is Ints) String() string {
func (is Ints[T]) String() string {
return ToString(is)
}

// Has given element
func (is Ints) Has(i int) bool {
func (is Ints[T]) Has(i T) bool {
for _, iv := range is {
if i == iv {
return true
Expand All @@ -26,24 +26,47 @@ func (is Ints) Has(i int) bool {
}

// First element value.
func (is Ints) First() int {
func (is Ints[T]) First(defVal ...T) T {
if len(is) > 0 {
return is[0]
}
panic("empty int slice")

if len(defVal) > 0 {
return defVal[0]
}
panic("empty integer slice")
}

// Last element value.
func (is Ints) Last() int {
func (is Ints[T]) Last(defVal ...T) T {
if len(is) > 0 {
return is[len(is)-1]
}
panic("empty int slice")

if len(defVal) > 0 {
return defVal[0]
}
panic("empty integer slice")
}

// Sort the int slice
func (is Ints) Sort() {
sort.Ints(is)
func (is Ints[T]) Sort() {
sort.Sort(is)
}

// Len get length
func (is Ints[T]) Len() int {
return len(is)
}

// Less compare two elements
func (is Ints[T]) Less(i, j int) bool {
return is[i] < is[j]
}

// Swap elements by indexes
func (is Ints[T]) Swap(i, j int) {
is[i], is[j] = is[j], is[i]
}

// Strings type
Expand Down Expand Up @@ -75,41 +98,69 @@ func (ss Strings) Contains(sub string) bool {
}

// First element value.
func (ss Strings) First() string {
func (ss Strings) First(defVal ...string) string {
if len(ss) > 0 {
return ss[0]
}

if len(defVal) > 0 {
return defVal[0]
}
panic("empty string list")
}

// Last element value.
func (ss Strings) Last() string {
func (ss Strings) Last(defVal ...string) string {
if len(ss) > 0 {
return ss[len(ss)-1]
}

if len(defVal) > 0 {
return defVal[0]
}
panic("empty string list")
}

// ScalarList definition for any type
type ScalarList[T comdef.ScalarType] []T
// Sort the string slice
func (ss Strings) Sort() {
sort.Strings(ss)
}

// SortedList definition for compared type
type SortedList[T comdef.Compared] []T

// Len get length
func (ls SortedList[T]) Len() int {
return len(ls)
}

// Less compare two elements
func (ls SortedList[T]) Less(i, j int) bool {
return ls[i] < ls[j]
}

// Swap elements by indexes
func (ls SortedList[T]) Swap(i, j int) {
ls[i], ls[j] = ls[j], ls[i]
}

// IsEmpty check
func (ls ScalarList[T]) IsEmpty() bool {
func (ls SortedList[T]) IsEmpty() bool {
return len(ls) == 0
}

// String to string
func (ls ScalarList[T]) String() string {
func (ls SortedList[T]) String() string {
return ToString(ls)
}

// Has given element
func (ls ScalarList[T]) Has(el T) bool {
func (ls SortedList[T]) Has(el T) bool {
return ls.Contains(el)
}

// Contains given element
func (ls ScalarList[T]) Contains(el T) bool {
func (ls SortedList[T]) Contains(el T) bool {
for _, v := range ls {
if v == el {
return true
Expand All @@ -119,39 +170,47 @@ func (ls ScalarList[T]) Contains(el T) bool {
}

// First element value.
func (ls ScalarList[T]) First() T {
func (ls SortedList[T]) First(defVal ...T) T {
if len(ls) > 0 {
return ls[0]
}

if len(defVal) > 0 {
return defVal[0]
}
panic("empty list")
}

// Last element value.
func (ls ScalarList[T]) Last() T {
func (ls SortedList[T]) Last(defVal ...T) T {
if ln := len(ls); ln > 0 {
return ls[ln-1]
}

if len(defVal) > 0 {
return defVal[0]
}
panic("empty list")
}

// Remove given element
func (ls ScalarList[T]) Remove(el T) ScalarList[T] {
func (ls SortedList[T]) Remove(el T) SortedList[T] {
return Filter(ls, func(v T) bool {
return v != el
})
}

// Filter the slice, default will filter zero value.
func (ls ScalarList[T]) Filter(filter ...comdef.MatchFunc[T]) ScalarList[T] {
func (ls SortedList[T]) Filter(filter ...comdef.MatchFunc[T]) SortedList[T] {
return Filter(ls, filter...)
}

// Map the slice to new slice. TODO syntax ERROR: Method cannot have type parameters
// func (ls ScalarList[T]) Map[V any](mapFn MapFn[T, V]) ScalarList[V] {
// func (ls SortedList[T]) Map[V any](mapFn MapFn[T, V]) SortedList[V] {
// return Map(ls, mapFn)
// }

// Sort the slice
// func (ls ScalarList[T]) Sort() {
// sort.Sort(ls)
// }
func (ls SortedList[T]) Sort() {
sort.Sort(ls)
}
50 changes: 24 additions & 26 deletions arrutil/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,20 @@ import (
)

func TestInts_methods(t *testing.T) {
tests := []struct {
is arrutil.Ints
val int
want bool
want2 string
}{
{
arrutil.Ints{12, 23},
12,
true,
"[12,23]",
},
}
ints := arrutil.Ints[int]{23, 10, 12}
assert.False(t, ints.Has(999))
assert.Eq(t, "[23,10,12]", ints.String())

for _, tt := range tests {
assert.Eq(t, tt.want, tt.is.Has(tt.val))
assert.False(t, tt.is.Has(999))
assert.Eq(t, tt.want2, tt.is.String())
}

ints := arrutil.Ints{23, 10, 12}
ints.Sort()
assert.Eq(t, "[10,12,23]", ints.String())
assert.Eq(t, 10, ints.First())
assert.Eq(t, 23, ints.Last())

ints = arrutil.Ints[int]{}
assert.Eq(t, 1, ints.First(1))
assert.Eq(t, 2, ints.Last(2))

t.Run("panic", func(t *testing.T) {
ints = arrutil.Ints{}
assert.Panics(t, func() {
ints.First()
})
Expand Down Expand Up @@ -71,8 +57,11 @@ func TestStrings_methods(t *testing.T) {
assert.Eq(t, "a", ss.First())
assert.Eq(t, "b", ss.Last())

ss = arrutil.Strings{}
assert.Eq(t, "default1", ss.First("default1"))
assert.Eq(t, "default2", ss.Last("default2"))

t.Run("panic", func(t *testing.T) {
ss = arrutil.Strings{}
assert.Panics(t, func() {
ss.First()
})
Expand All @@ -82,18 +71,27 @@ func TestStrings_methods(t *testing.T) {
})
}

func TestScalarList_methods(t *testing.T) {
ls := arrutil.ScalarList[string]{"a", "", "b"}
func TestSortedList_methods(t *testing.T) {
ls := arrutil.SortedList[string]{"a", "", "b"}
assert.Eq(t, "a", ls.First())
assert.Eq(t, "b", ls.Last())
assert.True(t, ls.Has("a"))
assert.False(t, ls.Has("e"))
assert.False(t, ls.IsEmpty())
assert.Eq(t, "[a,b]", ls.Filter().String())
assert.Eq(t, "[a,b]", ls.Remove("").String())

ls = ls.Remove("")
assert.Eq(t, "[a,b]", ls.String())

ls1 := arrutil.SortedList[int]{4, 3}
ls1.Sort()
assert.Eq(t, "[3,4]", ls1.String())

ls = arrutil.SortedList[string]{}
assert.Eq(t, "default1", ls.First("default1"))
assert.Eq(t, "default2", ls.Last("default2"))

t.Run("panic", func(t *testing.T) {
ls = arrutil.ScalarList[string]{}
assert.Panics(t, func() {
ls.First()
})
Expand Down
2 changes: 1 addition & 1 deletion comdef/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ type SimpleType interface {

// ScalarType interface type.
//
// it can be ordered, that supports the operators < <= >= >.
// TIP: has bool type, it cannot be ordered
//
// contains: (x)int, float, ~string, ~bool types
type ScalarType interface {
Expand Down
6 changes: 3 additions & 3 deletions fsutil/finder/matchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,9 @@ var timeNumReg = regexp.MustCompile(`(-?\d+)`)
//
// Usage:
//
// f := EmptyFinder()
// f.AddFilter(HumanModTime(">10m")) // before 10 minutes
// f.AddFilter(HumanModTime("<10m")) // latest 10 minutes, to Now
// f := finder.NewFinder()
// f.Include(HumanModTime(">10m")) // before 10 minutes
// f.Include(HumanModTime("<10m")) // latest 10 minutes, to Now
func HumanModTime(expr string) MatcherFunc {
opt := &timex.ParseRangeOpt{AutoSort: true}
// convert > to <, < to >
Expand Down

0 comments on commit fe184cf

Please sign in to comment.