Skip to content

Commit

Permalink
feat: 完善 stream 包对于 []string 的操作
Browse files Browse the repository at this point in the history
  • Loading branch information
kercylan98 committed Feb 5, 2024
1 parent 590d0a1 commit a2695f4
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 90 deletions.
8 changes: 4 additions & 4 deletions utils/stream/string.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type String[S ~string] struct {
str S
}

// Elem 返回字符串
// Elem 返回原始元素
func (s *String[S]) Elem() S {
return s.str
}
Expand Down Expand Up @@ -287,7 +287,7 @@ func (s *String[S]) Update(f func(S) S) *String[S] {
}

// Split 返回字符串切片
func (s *String[S]) Split(sep string) Strings[S] {
func (s *String[S]) Split(sep string) *Strings[S] {
slice := strings.Split(string(s.str), sep)
rep := make([]S, len(slice))
for i, v := range slice {
Expand All @@ -297,7 +297,7 @@ func (s *String[S]) Split(sep string) Strings[S] {
}

// SplitN 返回字符串切片
func (s *String[S]) SplitN(sep string, n int) Strings[S] {
func (s *String[S]) SplitN(sep string, n int) *Strings[S] {
slice := strings.SplitN(string(s.str), sep, n)
rep := make([]S, len(slice))
for i, v := range slice {
Expand All @@ -307,7 +307,7 @@ func (s *String[S]) SplitN(sep string, n int) Strings[S] {
}

// Batched 将字符串按照指定长度分组,最后一组可能小于指定长度
func (s *String[S]) Batched(size int) Strings[S] {
func (s *String[S]) Batched(size int) *Strings[S] {
var str = string(s.str)
var result = make([]S, 0, len(str)/size+1)
for len(str) >= size {
Expand Down
6 changes: 3 additions & 3 deletions utils/stream/string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,7 @@ func TestString_Split(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := stream.NewString(c.in).Split(c.sep)
for i, v := range got {
for i, v := range got.Elem() {
if v != c.want[i] {
t.Fatalf("NewString(%s).Split(%s) = %v; want %v", c.in, c.sep, got, c.want)
}
Expand All @@ -791,7 +791,7 @@ func TestString_SplitN(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := stream.NewString(c.in).SplitN(c.sep, c.n)
for i, v := range got {
for i, v := range got.Elem() {
if v != c.want[i] {
t.Fatalf("NewString(%s).SplitN(%s, %d) = %v; want %v", c.in, c.sep, c.n, got, c.want)
}
Expand All @@ -814,7 +814,7 @@ func TestString_Batched(t *testing.T) {
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := stream.NewString(c.in).Batched(c.size)
for i, v := range got {
for i, v := range got.Elem() {
if v != c.want[i] {
t.Fatalf("NewString(%s).Batched(%d) = %v; want %v", c.in, c.size, got, c.want)
}
Expand Down
142 changes: 59 additions & 83 deletions utils/stream/strings.go
Original file line number Diff line number Diff line change
@@ -1,123 +1,99 @@
package stream

import (
"sort"
)
import "strings"

// NewStrings 创建字符串切片
func NewStrings[S ~string](s ...S) Strings[S] {
var slice = make(Strings[S], len(s))
for i, v := range s {
slice[i] = v
}
return slice
func NewStrings[S ~string](s ...S) *Strings[S] {
return &Strings[S]{s}
}

// Strings 字符串切片
type Strings[S ~string] []S
type Strings[S ~string] struct {
s []S
}

// Elem 返回原始元素
func (s *Strings[S]) Elem() []S {
return s.s
}

// Len 返回切片长度
func (s *Strings[S]) Len() int {
return len(*s)
return len(s.s)
}

// Append 添加字符串
func (s *Strings[S]) Append(ss ...S) *Strings[S] {
*s = append(*s, NewStrings(ss...)...)
return s
}

// Clear 清空切片
func (s *Strings[S]) Clear() *Strings[S] {
*s = make(Strings[S], 0)
s.s = append(s.s, ss...)
return s
}

// Copy 复制切片
func (s *Strings[S]) Copy() *Strings[S] {
ss := make(Strings[S], len(*s))
copy(ss, *s)
return &ss
}

// Range 返回指定范围的切片
func (s *Strings[S]) Range(start, end int) *Strings[S] {
*s = (*s)[start:end]
return s
}

// First 返回第一个元素
func (s *Strings[S]) First() *String[S] {
return NewString((*s)[0])
// Join 连接字符串
func (s *Strings[S]) Join(sep S) *String[S] {
var cast = make([]string, len(s.s))
for i, v := range s.s {
cast[i] = string(v)
}
return NewString(S(strings.Join(cast, string(sep))))
}

// Last 返回最后一个元素
func (s *Strings[S]) Last() *String[S] {
return NewString((*s)[len(*s)-1])
// Choice 选择字符串
func (s *Strings[S]) Choice(i int) *String[S] {
return NewString(s.s[i])
}

// Index 返回指定的元素
func (s *Strings[S]) Index(i int) *String[S] {
return NewString((*s)[i])
// Choices 选择多个字符串
func (s *Strings[S]) Choices(i ...int) *Strings[S] {
var ss = make([]S, len(i))
for j, v := range i {
ss[j] = s.s[v]
}
return NewStrings(ss...)
}

// Reverse 反转切片
func (s *Strings[S]) Reverse() *Strings[S] {
for i, j := 0, len(*s)-1; i < j; i, j = i+1, j-1 {
(*s)[i], (*s)[j] = (*s)[j], (*s)[i]
}
return s
// ChoiceInRange 选择范围内的字符串
func (s *Strings[S]) ChoiceInRange(start, end int) *Strings[S] {
return NewStrings(s.s[start:end]...)
}

// Desc 降序排序
func (s *Strings[S]) Desc() *Strings[S] {
sort.Slice(*s, func(i, j int) bool {
return (*s)[i] > (*s)[j]
})
// Remove 移除字符串
func (s *Strings[S]) Remove(i int) *Strings[S] {
s.s = append(s.s[:i], s.s[i+1:]...)
return s
}

// Asc 升序排序
func (s *Strings[S]) Asc() *Strings[S] {
sort.Slice(*s, func(i, j int) bool {
return (*s)[i] < (*s)[j]
})
// Removes 移除多个字符串
func (s *Strings[S]) Removes(i ...int) *Strings[S] {
var ss = make([]S, 0, len(s.s)-len(i))
for j, v := range s.s {
for _, i := range i {
if j != i {
ss = append(ss, v)
}
}
}
s.s = ss
return s
}

// Sort 自定义排序
func (s *Strings[S]) Sort(f func(int, int) bool) *Strings[S] {
sort.Slice(*s, func(i, j int) bool {
return f(i, j)
})
// RemoveInRange 移除范围内的字符串
func (s *Strings[S]) RemoveInRange(start, end int) *Strings[S] {
s.s = append(s.s[:start], s.s[end:]...)
return s
}

// Unique 去重
func (s *Strings[S]) Unique() *Strings[S] {
m := map[S]struct{}{}
for _, v := range *s {
m[v] = struct{}{}
}
*s = make(Strings[S], 0, len(m))
for k := range m {
*s = append(*s, k)
}
// Clear 清空字符串
func (s *Strings[S]) Clear() *Strings[S] {
s.s = []S{}
return s
}

// Delete 删除指定位置的字符串
func (s *Strings[S]) Delete(i int) *Strings[S] {
*s = append((*s)[:i], (*s)[i+1:]...)
return s
// First 第一个字符串
func (s *Strings[S]) First() *String[S] {
return NewString(s.s[0])
}

// Each 遍历切片
func (s *Strings[S]) Each(f func(int, S) bool) *Strings[S] {
for i, v := range *s {
if !f(i, v) {
break
}
}
return s
// Last 最后一个字符串
func (s *Strings[S]) Last() *String[S] {
return NewString(s.s[len(s.s)-1])
}
90 changes: 90 additions & 0 deletions utils/stream/strings_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,91 @@
package stream_test

import (
"github.com/kercylan98/minotaur/utils/stream"
"testing"
)

func TestNewStrings(t *testing.T) {
var cases = []struct {
name string
in []string
want []string
}{
{name: "empty", in: []string{}, want: []string{}},
{name: "one", in: []string{"a"}, want: []string{"a"}},
{name: "two", in: []string{"a", "b"}, want: []string{"a", "b"}},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := stream.NewStrings(c.in...)
if got.Len() != len(c.want) {
t.Errorf("got %v, want %v", got, c.want)
}
})
}
}

func TestStrings_Elem(t *testing.T) {
var cases = []struct {
name string
in []string
want []string
}{
{name: "empty", in: []string{}, want: []string{}},
{name: "one", in: []string{"a"}, want: []string{"a"}},
{name: "two", in: []string{"a", "b"}, want: []string{"a", "b"}},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := stream.NewStrings(c.in...).Elem()
if len(got) != len(c.want) {
t.Errorf("got %v, want %v", got, c.want)
}
})
}
}

func TestStrings_Len(t *testing.T) {
var cases = []struct {
name string
in []string
want int
}{
{name: "empty", in: []string{}, want: 0},
{name: "one", in: []string{"a"}, want: 1},
{name: "two", in: []string{"a", "b"}, want: 2},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := stream.NewStrings(c.in...)
if got.Len() != c.want {
t.Errorf("got %v, want %v", got, c.want)
}
})
}
}

func TestStrings_Append(t *testing.T) {
var cases = []struct {
name string
in []string
append []string
want []string
}{
{name: "empty", in: []string{}, append: []string{"a"}, want: []string{"a"}},
{name: "one", in: []string{"a"}, append: []string{"b"}, want: []string{"a", "b"}},
{name: "two", in: []string{"a", "b"}, append: []string{"c"}, want: []string{"a", "b", "c"}},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
got := stream.NewStrings(c.in...).Append(c.append...)
if got.Len() != len(c.want) {
t.Errorf("got %v, want %v", got, c.want)
}
})
}
}

0 comments on commit a2695f4

Please sign in to comment.