1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00
Files
lancet/docs/api/packages/slice.md
donutloop 5e8a065eaa Slice: break (#200)
Splits a slice into two based on a predicate function. It starts appending to the second slice after the first element that matches the predicate. All elements after the first match are included in the second slice, regardless of whether they match the predicate or not.
2024-03-07 14:11:19 +08:00

52 KiB
Raw Blame History

Slice

slice 包包含操作切片的方法集合。

源码:

用法:

import (
    "github.com/duke-git/lancet/v2/slice"
)

目录

文档

AppendIfAbsent

当前切片中不包含值时,将该值追加到切片中

函数签名:

func AppendIfAbsent[T comparable](slice []T, item T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.AppendIfAbsent([]string{"a", "b"}, "b")
    result2 := slice.AppendIfAbsent([]string{"a", "b"}, "c")

    fmt.Println(result1)
    fmt.Println(result2)

    // Output:
    // [a b]
    // [a b c]
}

Contain

判断slice是否包含value

函数签名:

func Contain[T comparable](slice []T, target T) bool

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.Contain([]string{"a", "b", "c"}, "a")
    result2 := slice.Contain([]int{1, 2, 3}, 4)

    fmt.Println(result1)
    fmt.Println(result2)

    // Output:
    // true
    // false
}

ContainBy

根据predicate函数判断切片是否包含某个值。

函数签名:

func ContainBy[T any](slice []T, predicate func(item T) bool) bool

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    type foo struct {
        A string
        B int
    }

    array1 := []foo{{A: "1", B: 1}, {A: "2", B: 2}}
    result1 := slice.ContainBy(array1, func(f foo) bool { return f.A == "1" && f.B == 1 })
    result2 := slice.ContainBy(array1, func(f foo) bool { return f.A == "2" && f.B == 1 })

    array2 := []string{"a", "b", "c"}
    result3 := slice.ContainBy(array2, func(t string) bool { return t == "a" })
    result4 := slice.ContainBy(array2, func(t string) bool { return t == "d" })

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)
    fmt.Println(result4)

    // Output:
    // true
    // false
    // true
    // false
}

ContainSubSlice

判断slice是否包含subslice

函数签名:

func ContainSubSlice[T comparable](slice, subSlice []T) bool

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.ContainSubSlice([]string{"a", "b", "c"}, []string{"a", "b"})
    result2 := slice.ContainSubSlice([]string{"a", "b", "c"}, []string{"a", "d"})

    fmt.Println(result1)
    fmt.Println(result2)

    // Output:
    // true
    // false
}

Chunk

按照size参数均分slice

函数签名:

func Chunk[T any](slice []T, size int) [][]T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    arr := []string{"a", "b", "c", "d", "e"}

    result1 := slice.Chunk(arr, 1)
    result2 := slice.Chunk(arr, 2)
    result3 := slice.Chunk(arr, 3)
    result4 := slice.Chunk(arr, 4)
    result5 := slice.Chunk(arr, 5)

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)
    fmt.Println(result4)
    fmt.Println(result5)

    // Output:
    // [[a] [b] [c] [d] [e]]
    // [[a b] [c d] [e]]
    // [[a b c] [d e]]
    // [[a b c d] [e]]
    // [[a b c d e]]
}

Compact

去除slice中的假值false values are false, nil, 0, ""

函数签名:

func Compact[T comparable](slice []T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.Compact([]int{0})
    result2 := slice.Compact([]int{0, 1, 2, 3})
    result3 := slice.Compact([]string{"", "a", "b", "0"})
    result4 := slice.Compact([]bool{false, true, true})

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)
    fmt.Println(result4)

    // Output:
    // []
    // [1 2 3]
    // [a b 0]
    // [true true]
}

Concat

合并多个slices到slice中

函数签名:

func Concat[T any](slice []T, slices ...[]T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.Concat([]int{1, 2}, []int{3, 4})
    result2 := slice.Concat([]string{"a", "b"}, []string{"c"}, []string{"d"})

    fmt.Println(result1)
    fmt.Println(result2)

    // Output:
    // [1 2 3 4]
    // [a b c d]
}

Count

返回切片中指定元素的个数

函数签名:

func Count[T comparable](slice []T, item T) int

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 3, 4}

    result1 := slice.Count(nums, 1)
    result2 := slice.Count(nums, 3)

    fmt.Println(result1)
    fmt.Println(result2)

    // Output:
    // 1
    // 2
}

CountBy

遍历切片对每个元素执行函数predicate. 返回符合函数返回值为true的元素的个数.

函数签名:

func CountBy[T any](slice []T, predicate func(index int, item T) bool) int

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}

    isEven := func(i, num int) bool {
        return num%2 == 0
    }

    result := slice.CountBy(nums, isEven)

    fmt.Println(result)

    // Output:
    // 2
}

Difference

创建一个切片,其元素不包含在另一个给定切片中

函数签名:

func Difference[T comparable](slice, comparedSlice []T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    s1 := []int{1, 2, 3, 4, 5}
    s2 := []int{4, 5, 6}

    result := slice.Difference(s1, s2)

    fmt.Println(result)

    // Output:
    // [1 2 3]
}

DifferenceBy

将两个slice中的每个元素调用iteratee函数并比较它们的返回值如果不相等返回在slice中对应的值

函数签名:

func DifferenceBy[T comparable](slice []T, comparedSlice []T, iteratee func(index int, item T) T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    s1 := []int{1, 2, 3, 4, 5}
    s2 := []int{3, 4, 5}

    addOne := func(i int, v int) int {
        return v + 1
    }

    result := slice.DifferenceBy(s1, s2, addOne)

    fmt.Println(result)

    // Output:
    // [1 2]
}

DifferenceWith

接受比较器函数,该比较器被调用以将切片的元素与值进行比较。 结果值的顺序和引用由第一个切片确定

函数签名:

func DifferenceWith[T any](slice []T, comparedSlice []T, comparator func(value, otherValue T) bool) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    s1 := []int{1, 2, 3, 4, 5}
    s2 := []int{4, 5, 6, 7, 8}

    isDouble := func(v1, v2 int) bool {
        return v2 == 2*v1
    }

    result := slice.DifferenceWith(s1, s2, isDouble)

    fmt.Println(result)

    // Output:
    // [1 5]
}

DeleteAt

删除切片中指定索引的元素(不修改原切片)。

函数签名:

func DeleteAt[T any](slice []T, index int) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    chars := []string{"a", "b", "c", "d", "e"}

    result1 := slice.DeleteAt(chars, 0)
    result2 := slice.DeleteAt(chars, 4)
    result3 := slice.DeleteAt(chars, 5)
    result4 := slice.DeleteAt(chars, 6)

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)
    fmt.Println(result4)

    // Output:
    // [b c d e]
    // [a b c d]
    // [a b c d]
    // [a b c d]

}

DeleteRange

删除切片中指定索引范围的元素(不修改原切片)。

函数签名:

func DeleteRange[T any](slice []T, start, end int) []T 

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    chars := []string{"a", "b", "c", "d", "e"}

    result1 := DeleteRange(chars, 0, 0)
    result2 := DeleteRange(chars, 0, 1)
    result3 := DeleteRange(chars, 0, 3)
    result4 := DeleteRange(chars, 0, 4)
    result5 := DeleteRange(chars, 0, 5)

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)
    fmt.Println(result4)
    fmt.Println(result5)

    // Output:
    // [a b c d e]
    // [b c d e]
    // [d e]
    // [e]
    // []

}

Drop

从切片的头部删除n个元素。

函数签名:

func Drop[T any](slice []T, n int) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.Drop([]string{"a", "b", "c"}, 0)
    result2 := slice.Drop([]string{"a", "b", "c"}, 1)
    result3 := slice.Drop([]string{"a", "b", "c"}, -1)
    result4 := slice.Drop([]string{"a", "b", "c"}, 4)

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)
    fmt.Println(result4)

    // Output:
    // [a b c]
    // [b c]
    // [a b c]
    // []
}

DropRight

从切片的尾部删除n个元素。

函数签名:

func DropRight[T any](slice []T, n int) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.DropRight([]string{"a", "b", "c"}, 0)
    result2 := slice.DropRight([]string{"a", "b", "c"}, 1)
    result3 := slice.DropRight([]string{"a", "b", "c"}, -1)
    result4 := slice.DropRight([]string{"a", "b", "c"}, 4)

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)
    fmt.Println(result4)

    // Output:
    // [a b c]
    // [a b]
    // [a b c]
    // []
}

DropWhile

从切片的头部删除n个元素这个n个元素满足predicate函数返回true。

函数签名:

func DropWhile[T any](slice []T, predicate func(item T) bool) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.DropWhile(numbers, func(n int) bool {
        return n != 2
    })
    result2 := slice.DropWhile(numbers, func(n int) bool {
        return true
    })
    result3 := slice.DropWhile(numbers, func(n int) bool {
        return n == 0
    })

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)

    // Output:
    // [2 3 4 5]
    // []
    // [1 2 3 4 5]
}

DropRightWhile

从切片的尾部删除n个元素这个n个元素满足predicate函数返回true。

函数签名:

func DropRightWhile[T any](slice []T, predicate func(item T) bool) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5}

    result1 := slice.DropRightWhile(numbers, func(n int) bool {
        return n != 2
    })
    result2 := slice.DropRightWhile(numbers, func(n int) bool {
        return true
    })
    result3 := slice.DropRightWhile(numbers, func(n int) bool {
        return n == 0
    })

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)

    // Output:
    // [1 2]
    // []
    // [1 2 3 4 5]
}

Every

如果切片中的所有值都通过谓词函数则返回true。 函数签名应该是func(index int, value any) bool

函数签名:

func Every[T any](slice []T, predicate func(index int, item T) bool) bool

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 5}

    isEven := func(i, num int) bool {
        return num%2 == 0
    }

    result := slice.Every(nums, isEven)

    fmt.Println(result)

    // Output:
    // false
}

Equal

检查两个切片是否相等,相等条件:切片长度相同,元素顺序和值都相同

函数签名:

func Equal[T comparable](slice1, slice2 []T) bool

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    s1 := []int{1, 2, 3}
    s2 := []int{1, 2, 3}
    s3 := []int{1, 3, 2}

    result1 := slice.Equal(s1, s2)
    result2 := slice.Equal(s1, s3)

    fmt.Println(result1)
    fmt.Println(result2)

    // Output:
    // true
    // false
}

EqualWith

检查两个切片是否相等相等条件对两个切片的元素调用比较函数comparator返回true

函数签名:

func EqualWith[T, U any](slice1 []T, slice2 []U, comparator func(T, U) bool) bool

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    s1 := []int{1, 2, 3}
    s2 := []int{2, 4, 6}

    isDouble := func(a, b int) bool {
        return b == a*2
    }

    result := slice.EqualWith(s1, s2, isDouble)

    fmt.Println(result)

    // Output:
    // true
}

Filter

返回切片中通过predicate函数真值测试的所有元素

函数签名:

func Filter[T any](slice []T, predicate func(index int, item T) bool) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}

    isEven := func(i, num int) bool {
        return num%2 == 0
    }

    result := slice.Filter(nums, isEven)

    fmt.Println(result)

    // Output:
    // [2 4]
}

Find (废弃:使用 FindBy)

遍历slice的元素返回第一个通过predicate函数真值测试的元素

函数签名:

func Find[T any](slice []T, predicate func(index int, item T) bool) (*T, bool)

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}

    isEven := func(i, num int) bool {
        return num%2 == 0
    }

    result, ok := slice.Find(nums, isEven)

    fmt.Println(*result)
    fmt.Println(ok)

    // Output:
    // 2
    // true
}

FindBy

遍历slice的元素返回第一个通过predicate函数真值测试的元素

函数签名:

func FindBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool)

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}

    isEven := func(i, num int) bool {
        return num%2 == 0
    }

    result, ok := slice.FindBy(nums, isEven)

    fmt.Println(result)
    fmt.Println(ok)

    // Output:
    // 2
    // true
}

FindLast(废弃:使用 FindLastBy)

遍历slice的元素返回最后一个通过predicate函数真值测试的元素。

函数签名:

func FindLast[T any](slice []T, predicate func(index int, item T) bool) (*T, bool)

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}

    isEven := func(i, num int) bool {
        return num%2 == 0
    }

    result, ok := slice.FindLast(nums, isEven)

    fmt.Println(*result)
    fmt.Println(ok)

    // Output:
    // 4
    // true
}

FindLastBy

从遍历slice的元素返回最后一个通过predicate函数真值测试的元素。

函数签名:

func FindLastBy[T any](slice []T, predicate func(index int, item T) bool) (v T, ok bool)

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}

    isEven := func(i, num int) bool {
        return num%2 == 0
    }

    result, ok := slice.FindLastBy(nums, isEven)

    fmt.Println(result)
    fmt.Println(ok)

    // Output:
    // 4
    // true
}

Flatten

将切片压平一层

函数签名:

func Flatten(slice any) any

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    arrs := [][][]string{{{"a", "b"}}, {{"c", "d"}}}

    result := slice.Flatten(arrs)

    fmt.Println(result)

    // Output:
    // [[a b] [c d]]
}

FlattenDeep

flattens slice recursive.

函数签名:

func FlattenDeep(slice any) any

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    arrs := [][][]string{{{"a", "b"}}, {{"c", "d"}}}

    result := slice.FlattenDeep(arrs)

    fmt.Println(result)

    // Output:
    // [a b c d]
}

ForEach

遍历切片的元素并为每个元素调用iteratee函数

函数签名:

func ForEach[T any](slice []T, iteratee func(index int, item T))

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3}

    var result []int
    addOne := func(_ int, v int) {
        result = append(result, v+1)
    }

    slice.ForEach(nums, addOne)

    fmt.Println(result)

    // Output:
    // [2 3 4]
}

ForEachWithBreak

遍历切片的元素并为每个元素调用iteratee函数当iteratee函数返回false时终止遍历。

函数签名:

func ForEachWithBreak[T any](slice []T, iteratee func(index int, item T) bool)

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5}

    var sum int

    slice.ForEachWithBreak(numbers, func(_, n int) bool {
        if n > 3 {
            return false
        }
        sum += n
        return true
    })

    fmt.Println(sum)

    // Output:
    // 6
}

GroupBy

迭代切片的元素,每个元素将按条件分组,返回两个切片

函数签名:

func GroupBy[T any](slice []T, groupFn func(index int, item T) bool) ([]T, []T)

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}

    isEven := func(i, num int) bool {
        return num%2 == 0
    }

    even, odd := slice.GroupBy(nums, isEven)

    fmt.Println(even)
    fmt.Println(odd)

    // Output:
    // [2 4]
    // [1 3 5]
}

GroupWith

创建一个mapkey是iteratee遍历slice中的每个元素返回的结果。 分组值的顺序是由他们出现在slice中的顺序确定的。每个键对应的值负责生成key的元素组成的数组。iteratee调用1个参数 (value)

函数签名:

func GroupWith[T any, U comparable](slice []T, iteratee func(T) U) map[U][]T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []float64{6.1, 4.2, 6.3}

    floor := func(num float64) float64 {
        return math.Floor(num)
    }

    result := slice.GroupWith(nums, floor) //map[float64][]float64

    fmt.Println(result)

    // Output:
    // map[4:[4.2] 6:[6.1 6.3]]
}

IntSlice (已弃用: 使用 go1.18+泛型代替)

将接口切片转换为int切片

函数签名:

func IntSlice(slice any) []int

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []interface{}{1, 2, 3}

    result := slice.IntSlice(nums) //[]int{1, 2, 3}
    fmt.Println(result)

    // Output:
    // [1 2 3]
}

InterfaceSlice(已弃用: 使用 go1.18+泛型代替)

将值转换为接口切片

函数签名:

func InterfaceSlice(slice any) []any

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    strs := []string{"a", "b", "c"}

    result := slice.InterfaceSlice(strs) //[]interface{}{"a", "b", "c"}
    fmt.Println(result)

    // Output:
    // [a b c]
}

Intersection

多个切片的交集

函数签名:

func Intersection[T comparable](slices ...[]T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums1 := []int{1, 2, 3}
    nums2 := []int{2, 3, 4}

    result := slice.Intersection(nums1, nums2)

    fmt.Println(result)

    // Output:
    // [2 3]
}

InsertAt

将元素插入到索引处的切片中

函数签名:

func InsertAt[T any](slice []T, index int, value any) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.InsertAt([]string{"a", "b", "c"}, 0, "1")
    result2 := slice.InsertAt([]string{"a", "b", "c"}, 1, "1")
    result3 := slice.InsertAt([]string{"a", "b", "c"}, 2, "1")
    result4 := slice.InsertAt([]string{"a", "b", "c"}, 3, "1")
    result5 := slice.InsertAt([]string{"a", "b", "c"}, 0, []string{"1", "2", "3"})

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)
    fmt.Println(result4)
    fmt.Println(result5)

    // Output:
    // [1 a b c]
    // [a 1 b c]
    // [a b 1 c]
    // [a b c 1]
    // [1 2 3 a b c]
}

IndexOf

返回在切片中找到值的第一个匹配项的索引,如果找不到值,则返回-1

函数签名:

func IndexOf[T comparable](slice []T, item T) int

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    strs := []string{"a", "a", "b", "c"}

    result1 := slice.IndexOf(strs, "a")
    result2 := slice.IndexOf(strs, "d")

    fmt.Println(result1)
    fmt.Println(result2)

    // Output:
    // 0
    // -1
}

LastIndexOf

返回在切片中找到最后一个值的索引,如果找不到该值,则返回-1

函数签名:

func LastIndexOf[T comparable](slice []T, item T) int

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    strs := []string{"a", "a", "b", "c"}

    result1 := slice.LastIndexOf(strs, "a")
    result2 := slice.LastIndexOf(strs, "d")

    fmt.Println(result1)
    fmt.Println(result2)

    // Output:
    // 1
    // -1
}

Map

对slice中的每个元素执行map函数以创建一个新切片

函数签名:

func Map[T any, U any](slice []T, iteratee func(index int, item T) U) []U

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3}

    addOne := func(_ int, v int) int {
        return v + 1
    }

    result := slice.Map(nums, addOne)

    fmt.Println(result)

    // Output:
    // [2 3 4]
}

FilterMap

返回一个将filter和map操作应用于给定切片的切片。 iteratee回调函数应该返回两个值1结果值。2结果值是否应该被包含在返回的切片中。

函数签名:

func FilterMap[T any, U any](slice []T, iteratee func(index int, item T) (U, bool)) []U

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}

    getEvenNumStr := func(i, num int) (string, bool) {
        if num%2 == 0 {
            return strconv.FormatInt(int64(num), 10), true
        }
        return "", false
    }

    result := slice.FilterMap(nums, getEvenNumStr)

    fmt.Printf("%#v", result)

    // Output:
    // []string{"2", "4"}
}

FlatMap

将切片转换为其它类型切片。

函数签名:

func FlatMap[T any, U any](slice []T, iteratee func(index int, item T) []U) []U

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4}

    result := slice.FlatMap(nums, func(i int, num int) []string {
        s := "hi-" + strconv.FormatInt(int64(num), 10)
        return []string{s}
    })

    fmt.Printf("%#v", result)

    // Output:
    // []string{"hi-1", "hi-2", "hi-3", "hi-4"}
}

Merge

合并多个切片(不会消除重复元素).

函数签名:

func Merge[T any](slices ...[]T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums1 := []int{1, 2, 3}
    nums2 := []int{3, 4}

    result := slice.Merge(nums1, nums2)

    fmt.Println(result)

    // Output:
    // [1 2 3 3 4]
}

Reverse

反转切片中的元素顺序

函数签名:

func Reverse[T any](slice []T)

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    strs := []string{"a", "b", "c", "d"}

    slice.Reverse(strs)

    fmt.Println(strs)

    // Output:
    // [d c b a]
}

Reduce

将切片中的元素依次运行iteratee函数返回运行结果(废弃建议使用ReduceBy)

函数签名:

func Reduce[T any](slice []T, iteratee func(index int, item1, item2 T) T, initial T) T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3}

    sum := func(_ int, v1, v2 int) int {
        return v1 + v2
    }

    result := slice.Reduce(nums, sum, 0)

    fmt.Println(result)

    // Output:
    // 6
}

ReduceBy

对切片元素执行reduce操作。

函数签名:

func ReduceBy[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.ReduceBy([]int{1, 2, 3, 4}, 0, func(_ int, item int, agg int) int {
        return agg + item
    })

    result2 := slice.ReduceBy([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
        return agg + fmt.Sprintf("%v", item)
    })

    fmt.Println(result1)
    fmt.Println(result2)

    // Output:
    // 10
    // 1234
}

ReduceRight

类似ReduceBy操作迭代切片元素顺序从右至左。

函数签名:

func ReduceRight[T any, U any](slice []T, initial U, reducer func(index int, item T, agg U) U) U

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result := slice.ReduceRight([]int{1, 2, 3, 4}, "", func(_ int, item int, agg string) string {
        return agg + fmt.Sprintf("%v", item)
    })

    fmt.Println(result)

    // Output:
    // 4321
}

Replace

返回切片的副本其中前n个不重叠的old替换为new

函数签名:

func Replace[T comparable](slice []T, old T, new T, n int) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    strs := []string{"a", "b", "c", "a"}

    result1 := slice.Replace(strs, "a", "x", 0)
    result2 := slice.Replace(strs, "a", "x", 1)
    result3 := slice.Replace(strs, "a", "x", 2)
    result4 := slice.Replace(strs, "a", "x", 3)
    result5 := slice.Replace(strs, "a", "x", -1)

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)
    fmt.Println(result4)
    fmt.Println(result5)

    // Output:
    // [a b c a]
    // [x b c a]
    // [x b c x]
    // [x b c x]
    // [x b c x]
}

ReplaceAll

返回切片的副本将其中old全部替换为new

函数签名:

func ReplaceAll[T comparable](slice []T, old T, new T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result := slice.ReplaceAll([]string{"a", "b", "c", "a"}, "a", "x")

    fmt.Println(result)

    // Output:
    // [x b c x]
}

Repeat

创建一个切片包含n个传入的item

函数签名:

func Repeat[T any](item T, n int) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result := slice.Repeat("a", 3)

    fmt.Println(result)

    // Output:
    // [a a a]
}

Shuffle

随机打乱切片中的元素顺序

函数签名:

func Shuffle[T any](slice []T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}
    result := slice.Shuffle(nums)

    fmt.Println(res)

    // Output:
    // [3 1 5 4 2] (random order)
}

IsAscending

检查切片元素是否按升序排列。

函数签名:

func IsAscending[T constraints.Ordered](slice []T) bool

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.IsAscending([]int{1, 2, 3, 4, 5})
    result2 := slice.IsAscending([]int{5, 4, 3, 2, 1})
    result3 := slice.IsAscending([]int{2, 1, 3, 4, 5})

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)

    // Output:
    // true
    // false
    // false
}

IsDescending

检查切片元素是否按降序排列。

函数签名:

func IsDescending[T constraints.Ordered](slice []T) bool

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.IsDescending([]int{5, 4, 3, 2, 1})
    result2 := slice.IsDescending([]int{1, 2, 3, 4, 5})
    result3 := slice.IsDescending([]int{2, 1, 3, 4, 5})

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)

    // Output:
    // true
    // false
    // false
}

IsSorted

检查切片元素是否是有序的(升序或降序)。

函数签名:

func IsSorted[T constraints.Ordered](slice []T) bool

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.IsSorted([]int{5, 4, 3, 2, 1})
    result2 := slice.IsSorted([]int{1, 2, 3, 4, 5})
    result3 := slice.IsSorted([]int{2, 1, 3, 4, 5})

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)

    // Output:
    // true
    // true
    // false
}

IsSortedByKey

通过iteratee函数检查切片元素是否是有序的。

函数签名:

func IsSortedByKey[T any, K constraints.Ordered](slice []T, iteratee func(item T) K) bool

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.IsSortedByKey([]string{"a", "ab", "abc"}, func(s string) int {
        return len(s)
    })
    result2 := slice.IsSortedByKey([]string{"abc", "ab", "a"}, func(s string) int {
        return len(s)
    })
    result3 := slice.IsSortedByKey([]string{"abc", "a", "ab"}, func(s string) int {
        return len(s)
    })

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)

    // Output:
    // true
    // true
    // false
}

Sort

对任何有序类型(数字或字符串)的切片进行排序,使用快速排序算法。 默认排序顺序为升序 (asc),如果需要降序,请将参数 `sortOrder` 设置为 `desc`。 Ordered类型数字所有整数浮点数或字符串。

函数签名:

func Sort[T constraints.Ordered](slice []T, sortOrder ...string)

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    numbers := []int{1, 4, 3, 2, 5}

    slice.Sort(numbers)
    fmt.Println(numbers) // [1 2 3 4 5]

    slice.Sort(numbers, "desc")
    fmt.Println(numbers) // [5 4 3 2 1]

    strings := []string{"a", "d", "c", "b", "e"}

    slice.Sort(strings)
    fmt.Println(strings) //[a b c d e}

    slice.Sort(strings, "desc")
    fmt.Println(strings) //[e d c b a]
}

SortBy

按照less函数确定的升序规则对切片进行排序。排序不保证稳定性

函数签名:

func SortBy[T any](slice []T, less func(a, b T) bool)

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    numbers := []int{1, 4, 3, 2, 5}

    slice.SortBy(numbers, func(a, b int) bool {
        return a < b
    })
    fmt.Println(numbers) // [1 2 3 4 5]

    type User struct {
        Name string
        Age  uint
    }

    users := []User{
        {Name: "a", Age: 21},
        {Name: "b", Age: 15},
        {Name: "c", Age: 100}}

    slice.SortBy(users, func(a, b User) bool {
        return a.Age < b.Age
    })

    fmt.Printf("sort users by age: %v", users)

    // output
    // [{b 15} {a 21} {c 100}]
}

SortByField

按字段对结构体切片进行排序。slice元素应为struct排序字段field类型应为int、uint、string或bool。 默认排序类型是升序asc如果是降序设置 sortType 为 desc

函数签名:

func SortByField(slice any, field string, sortType ...string) error

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    type User struct {
        Name string
        Age  uint
    }

    users := []User{
        {Name: "a", Age: 21},
        {Name: "b", Age: 15},
        {Name: "c", Age: 100}}

    err := slice.SortByField(users, "Age", "desc")
    if err != nil {
        return
    }

    fmt.Println(users)

    // Output:
    // [{c 100} {a 21} {b 15}]
}

Some

如果列表中的任何值通过谓词函数则返回true

函数签名:

func Some[T any](slice []T, predicate func(index int, item T) bool) bool

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 5}

    isEven := func(i, num int) bool {
        return num%2 == 0
    }

    result := slice.Some(nums, isEven)

    fmt.Println(result)

    // Output:
    // true
}

StringSlice(已弃用: 使用 go1.18+泛型代替)

将接口切片转换为字符串切片

函数签名:

func StringSlice(slice any) []string

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    strs := []interface{}{"a", "b", "c"}

    result := slice.StringSlice(strs) //[]string{"a", "b", "c"}
    fmt.Println(result)

    // Output:
    // [a b c]
}

SymmetricDifference

返回一个切片,其中的元素存在于参数切片中,但不同时存储在于参数切片中(交集取反)

函数签名:

func SymmetricDifference[T comparable](slices ...[]T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums1 := []int{1, 2, 3}
    nums2 := []int{1, 2, 4}

    result := slice.SymmetricDifference(nums1, nums2)

    fmt.Println(result)

    // Output:
    // [3 4]
}

ToSlice

将可变参数转为切片

函数签名:

func ToSlice[T any](items ...T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result := slice.ToSlice("a", "b", "c")

    fmt.Println(result)

    // Output:
    // [a b c]
}

ToSlicePointer

将可变参数转为指针切片

函数签名:

func ToSlicePointer[T any](items ...T) []*T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    str1 := "a"
    str2 := "b"

    result := slice.ToSlicePointer(str1, str2)

    expect := []*string{&str1, &str2}

    isEqual := reflect.DeepEqual(result, expect)

    fmt.Println(isEqual)

    // Output:
    // true
}

Unique

删除切片中的重复元素

函数签名:

func Unique[T comparable](slice []T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result := slice.Unique([]string{"a", "a", "b"})
    fmt.Println(result)

    // Output:
    // [a b]
}

UniqueBy

对切片的每个元素调用iteratee函数然后删除重复元素

函数签名:

func UniqueBy[T comparable](slice []T, iteratee func(item T) T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5, 6}
    result := slice.UniqueBy(nums, func(val int) int {
        return val % 3
    })

    fmt.Println(result)

    // Output:
    // [1 2 0]
}

Union

合并多个切片

函数签名:

func Union[T comparable](slices ...[]T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums1 := []int{1, 3, 4, 6}
    nums2 := []int{1, 2, 5, 6}

    result := slice.Union(nums1, nums2)

    fmt.Println(result)

    // Output:
    // [1 3 4 6 2 5]
}

UnionBy

对切片的每个元素调用函数后,合并多个切片

函数签名:

func UnionBy[T any, V comparable](predicate func(item T) V, slices ...[]T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4}

    divideTwo := func(n int) int {
        return n / 2
    }
    result := slice.UnionBy(divideTwo, nums)

    fmt.Println(result)

    // Output:
    // [1 2 4]
}

UpdateAt

更新索引处的切片元素。 如果index < 0或 index <= len(slice),将返回错误

函数签名:

func UpdateAt[T any](slice []T, index int, value T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result1 := slice.UpdateAt([]string{"a", "b", "c"}, -1, "1")
    result2 := slice.UpdateAt([]string{"a", "b", "c"}, 0, "1")
    result3 := slice.UpdateAt([]string{"a", "b", "c"}, 1, "1")
    result4 := slice.UpdateAt([]string{"a", "b", "c"}, 2, "1")
    result5 := slice.UpdateAt([]string{"a", "b", "c"}, 3, "1")

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)
    fmt.Println(result4)
    fmt.Println(result5)

    // Output:
    // [a b c]
    // [1 b c]
    // [a 1 c]
    // [a b 1]
    // [a b c]
}

Without

创建一个不包括所有给定值的切片

函数签名:

func Without[T comparable](slice []T, items ...T) []T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result := slice.Without([]int{1, 2, 3, 4}, 1, 2)

    fmt.Println(result)

    // Output:
    // [3 4]
}

KeyBy

将切片每个元素调用函数后转为map。

函数签名:

func KeyBy[T any, U comparable](slice []T, iteratee func(item T) U) map[U]T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    result := slice.KeyBy([]string{"a", "ab", "abc"}, func(str string) int {
        return len(str)
    })

    fmt.Println(result)

    // Output:
    // map[1:a 2:ab 3:abc]
}

Join

用指定的分隔符链接切片元素。

函数签名:

func Join[T any](s []T, separator string) string

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}

    result1 := slice.Join(nums, ",")
    result2 := slice.Join(nums, "-")

    fmt.Println(result1)
    fmt.Println(result2)

    // Output:
    // 1,2,3,4,5
    // 1-2-3-4-5
}

Partition

根据给定的predicate判断函数分组切片元素。

函数签名:

func Partition[T any](slice []T, predicates ...func(item T) bool) [][]T

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}

    result1 := slice.Partition(nums)
    result2 := slice.Partition(nums, func(n int) bool { return n%2 == 0 })
    result3 := slice.Partition(nums, func(n int) bool { return n == 1 || n == 2 }, func(n int) bool { return n == 2 || n == 3 || n == 4 })

    fmt.Println(result1)
    fmt.Println(result2)
    fmt.Println(result3)

    // Output:
    // [[1 2 3 4 5]]
    // [[2 4] [1 3 5]]
    // [[1 2] [3 4] [5]]
}

Random

随机返回切片中元素以及下标, 当切片长度为0时返回下标-1

函数签名:

func Random[T any](slice []T) (val T, idx int)

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}

    val, idx := slice.Random(nums)
    if idx >= 0 && idx < len(nums) && slice.Contain(nums, val) {
        fmt.Println("okk")
    }
    // Output:
    // okk
}

SetToDefaultIf

根据给定给定的predicate判定函数来修改切片中的元素。对于满足的元素将其替换为指定的默认值同时保持元素在切片中的位置不变。函数返回修改后的切片以及被修改的元素个数。

函数签名:

func SetToDefaultIf[T any](slice []T, predicate func(T) bool) ([]T, int)

示例:运行

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    strs := []string{"a", "b", "a", "c", "d", "a"}
	modifiedStrs, count := slice.SetToDefaultIf(strs, func(s string) bool { return "a" == s })
	
    fmt.Println(modifiedStrs)
	fmt.Println(count)
	
    // Output:
	// [ b  c d ]
	// 3
}

Break

TBD

示例:

func Break[T any](values []T, predicate func(T) bool) ([]T, []T)

Example:

import (
    "fmt"
    "github.com/duke-git/lancet/v2/slice"
)

func main() {
    nums := []int{1, 2, 3, 4, 5}
    even := func(n int) bool { return n%2 == 0 }

    resultEven, resultAfterFirstEven := Break(nums, even)
    
    fmt.Println(resultEven)
    fmt.Println(resultAfterFirstEven)
    
    // Output:
    // [1]
    // [2 3 4 5]
}