feat: 完善 stream 包对于 []string 的操作
This commit is contained in:
parent
590d0a1887
commit
a2695f4fcf
|
@ -15,7 +15,7 @@ type String[S ~string] struct {
|
||||||
str S
|
str S
|
||||||
}
|
}
|
||||||
|
|
||||||
// Elem 返回字符串
|
// Elem 返回原始元素
|
||||||
func (s *String[S]) Elem() S {
|
func (s *String[S]) Elem() S {
|
||||||
return s.str
|
return s.str
|
||||||
}
|
}
|
||||||
|
@ -287,7 +287,7 @@ func (s *String[S]) Update(f func(S) S) *String[S] {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split 返回字符串切片
|
// 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)
|
slice := strings.Split(string(s.str), sep)
|
||||||
rep := make([]S, len(slice))
|
rep := make([]S, len(slice))
|
||||||
for i, v := range slice {
|
for i, v := range slice {
|
||||||
|
@ -297,7 +297,7 @@ func (s *String[S]) Split(sep string) Strings[S] {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SplitN 返回字符串切片
|
// 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)
|
slice := strings.SplitN(string(s.str), sep, n)
|
||||||
rep := make([]S, len(slice))
|
rep := make([]S, len(slice))
|
||||||
for i, v := range slice {
|
for i, v := range slice {
|
||||||
|
@ -307,7 +307,7 @@ func (s *String[S]) SplitN(sep string, n int) Strings[S] {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Batched 将字符串按照指定长度分组,最后一组可能小于指定长度
|
// 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 str = string(s.str)
|
||||||
var result = make([]S, 0, len(str)/size+1)
|
var result = make([]S, 0, len(str)/size+1)
|
||||||
for len(str) >= size {
|
for len(str) >= size {
|
||||||
|
|
|
@ -767,7 +767,7 @@ func TestString_Split(t *testing.T) {
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
got := stream.NewString(c.in).Split(c.sep)
|
got := stream.NewString(c.in).Split(c.sep)
|
||||||
for i, v := range got {
|
for i, v := range got.Elem() {
|
||||||
if v != c.want[i] {
|
if v != c.want[i] {
|
||||||
t.Fatalf("NewString(%s).Split(%s) = %v; want %v", c.in, c.sep, got, c.want)
|
t.Fatalf("NewString(%s).Split(%s) = %v; want %v", c.in, c.sep, got, c.want)
|
||||||
}
|
}
|
||||||
|
@ -791,7 +791,7 @@ func TestString_SplitN(t *testing.T) {
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
got := stream.NewString(c.in).SplitN(c.sep, c.n)
|
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] {
|
if v != c.want[i] {
|
||||||
t.Fatalf("NewString(%s).SplitN(%s, %d) = %v; want %v", c.in, c.sep, c.n, got, c.want)
|
t.Fatalf("NewString(%s).SplitN(%s, %d) = %v; want %v", c.in, c.sep, c.n, got, c.want)
|
||||||
}
|
}
|
||||||
|
@ -814,7 +814,7 @@ func TestString_Batched(t *testing.T) {
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
got := stream.NewString(c.in).Batched(c.size)
|
got := stream.NewString(c.in).Batched(c.size)
|
||||||
for i, v := range got {
|
for i, v := range got.Elem() {
|
||||||
if v != c.want[i] {
|
if v != c.want[i] {
|
||||||
t.Fatalf("NewString(%s).Batched(%d) = %v; want %v", c.in, c.size, got, c.want)
|
t.Fatalf("NewString(%s).Batched(%d) = %v; want %v", c.in, c.size, got, c.want)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,123 +1,99 @@
|
||||||
package stream
|
package stream
|
||||||
|
|
||||||
import (
|
import "strings"
|
||||||
"sort"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewStrings 创建字符串切片
|
// NewStrings 创建字符串切片
|
||||||
func NewStrings[S ~string](s ...S) Strings[S] {
|
func NewStrings[S ~string](s ...S) *Strings[S] {
|
||||||
var slice = make(Strings[S], len(s))
|
return &Strings[S]{s}
|
||||||
for i, v := range s {
|
|
||||||
slice[i] = v
|
|
||||||
}
|
|
||||||
return slice
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strings 字符串切片
|
// Strings 字符串切片
|
||||||
type Strings[S ~string] []S
|
type Strings[S ~string] struct {
|
||||||
|
s []S
|
||||||
|
}
|
||||||
|
|
||||||
|
// Elem 返回原始元素
|
||||||
|
func (s *Strings[S]) Elem() []S {
|
||||||
|
return s.s
|
||||||
|
}
|
||||||
|
|
||||||
// Len 返回切片长度
|
// Len 返回切片长度
|
||||||
func (s *Strings[S]) Len() int {
|
func (s *Strings[S]) Len() int {
|
||||||
return len(*s)
|
return len(s.s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append 添加字符串
|
// Append 添加字符串
|
||||||
func (s *Strings[S]) Append(ss ...S) *Strings[S] {
|
func (s *Strings[S]) Append(ss ...S) *Strings[S] {
|
||||||
*s = append(*s, NewStrings(ss...)...)
|
s.s = append(s.s, ss...)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear 清空切片
|
// 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))))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choice 选择字符串
|
||||||
|
func (s *Strings[S]) Choice(i int) *String[S] {
|
||||||
|
return NewString(s.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...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChoiceInRange 选择范围内的字符串
|
||||||
|
func (s *Strings[S]) ChoiceInRange(start, end int) *Strings[S] {
|
||||||
|
return NewStrings(s.s[start:end]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove 移除字符串
|
||||||
|
func (s *Strings[S]) Remove(i int) *Strings[S] {
|
||||||
|
s.s = append(s.s[:i], s.s[i+1:]...)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveInRange 移除范围内的字符串
|
||||||
|
func (s *Strings[S]) RemoveInRange(start, end int) *Strings[S] {
|
||||||
|
s.s = append(s.s[:start], s.s[end:]...)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear 清空字符串
|
||||||
func (s *Strings[S]) Clear() *Strings[S] {
|
func (s *Strings[S]) Clear() *Strings[S] {
|
||||||
*s = make(Strings[S], 0)
|
s.s = []S{}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy 复制切片
|
// First 第一个字符串
|
||||||
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] {
|
func (s *Strings[S]) First() *String[S] {
|
||||||
return NewString((*s)[0])
|
return NewString(s.s[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last 返回最后一个元素
|
// Last 最后一个字符串
|
||||||
func (s *Strings[S]) Last() *String[S] {
|
func (s *Strings[S]) Last() *String[S] {
|
||||||
return NewString((*s)[len(*s)-1])
|
return NewString(s.s[len(s.s)-1])
|
||||||
}
|
|
||||||
|
|
||||||
// Index 返回指定的元素
|
|
||||||
func (s *Strings[S]) Index(i int) *String[S] {
|
|
||||||
return NewString((*s)[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
// Desc 降序排序
|
|
||||||
func (s *Strings[S]) Desc() *Strings[S] {
|
|
||||||
sort.Slice(*s, func(i, j int) bool {
|
|
||||||
return (*s)[i] > (*s)[j]
|
|
||||||
})
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Asc 升序排序
|
|
||||||
func (s *Strings[S]) Asc() *Strings[S] {
|
|
||||||
sort.Slice(*s, func(i, j int) bool {
|
|
||||||
return (*s)[i] < (*s)[j]
|
|
||||||
})
|
|
||||||
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)
|
|
||||||
})
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete 删除指定位置的字符串
|
|
||||||
func (s *Strings[S]) Delete(i int) *Strings[S] {
|
|
||||||
*s = append((*s)[:i], (*s)[i+1:]...)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,91 @@
|
||||||
package stream_test
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue