An open API service indexing awesome lists of open source software.

https://github.com/didi/collection

go collection package for fasting coding
https://github.com/didi/collection

Last synced: 7 months ago
JSON representation

go collection package for fasting coding

Awesome Lists containing this project

README

          

# collection

Collection包目标是用于替换golang原生的Slice,使用场景是在大量不追求极致性能,追求业务开发效能的场景。

| 版本 | 说明 |
| ------| ------ |
| 1.2.0 | 增加对象指针数组,增加测试覆盖率, 增加ToInterfaces方法 |
| 1.1.2 | 增加一些空数组的判断,解决一些issue |
| 1.1.1 | 对collection包进行了json解析和反解析的支持,对mix类型支持了SetField和RemoveFields的类型设置 |
| 1.1.0 | 增加了对int32的支持,增加了延迟加载,增加了Copy函数,增加了compare从ICollection传递到IMix,使用快排加速了Sort方法 |
| 1.0.1 | 第一次发布 |

`go get github.com/jianfengye/collection`

创建collection库的说明文章见:[一个让业务开发效率提高10倍的golang库](https://www.cnblogs.com/yjf512/p/10818089.html)

Collection包目前支持的元素类型:int32, int, int64, float32, float64, string, struct。

使用下列几个方法进行初始化Collection:

```go
NewIntCollection(objs []int) *IntCollection

NewInt64Collection(objs []int64) *Int64Collection

NewInt32Collection(objs []int32) *Int32Collection

NewFloat64Collection(objs []float64) *Float64Collection

NewFloat32Collection(objs []float32) *Float32Collection

NewStrCollection(objs []string) *StrCollection

NewObjCollection(objs interface{}) *ObjCollection

NewObjPointCollection(objs interface{}) *ObjPointCollection
```

Collection的Error是随着Collection对象走,或者下沉到IMix中,所以可以放心在ICollection和IMix进行链式调用,只需要最后进行一次错误检查即可。

```
ret, err := objColl.Map(func(item interface{}, key int) IMix {
foo := item.(Foo)
return NewMix(foo.A)
}).Reduce(func(carry IMix, item IMix) IMix {
ret, _ := carry.ToString()
join, _ := item.ToString()
return NewMix(ret + join)
}).ToString()
if err != nil {
...
}
```

支持的方法有:

[Append](#Append) 挂载一个元素到当前Collection

[Avg](#Avg) 返回Collection的数值平均数,只能数值类型coll调用

[Contain](#Contain) 判断一个元素是否在Collection中。非数值类型必须设置对象compare方法。

[Copy](#Copy) 根据当前的数组,创造出一个同类型的数组

[DD](#DD) 按照友好的格式展示Collection

[Diff](#Diff) 获取前一个Collection不在后一个Collection中的元素, 只能数值类型Diff调用

[Each](#Each) 对Collection中的每个函数都进行一次函数调用

[Every](#Every) 判断Collection中的每个元素是否都符合某个条件

[ForPage](#ForPage) 将Collection函数进行分页

[Filter](#Filter) 根据过滤函数获取Collection过滤后的元素

[First](#First) 获取符合过滤条件的第一个元素

[Index](#Index) 获取元素中的第几个元素,下标从0开始

[IsEmpty](#IsEmpty) 判断一个Collection是否为空

[IsNotEmpty](#IsNotEmpty) 判断一个Collection是否为空

[Join](#Join) 将Collection中的元素按照某种方式聚合成字符串

[Last](#Last) 获取该Collection中满足过滤的最后一个元素

[Merge](#Merge) 将两个Collection的元素进行合并

[Map](#Map) 对Collection中的每个函数都进行一次函数调用

[Mode](#Mode) 获取Collection中的众数

[Max](#Max) 获取Collection中的最大元素

[Min](#Min) 获取Collection中的最小元素

[Median](#Median) 获取Collection的中位数

[NewEmpty](#NewEmpty) 根据当前的数组,创造出一个同类型的数组

[Nth](#Nth) 获取从offset偏移量开始的每第n个

[Pad](#Pad) 填充Collection数组

[Pop](#Pop) 从Collection右侧弹出一个元素

[Push](#Push) 往Collection的右侧推入一个元素

[Prepend](#Prepend) 往Collection左侧加入元素

[Pluck](#Pluck) 将对象数组中的某个元素提取出来组成一个新的Collection

[Reject](#Reject) 将满足过滤条件的元素删除

[Reduce](#Reduce) 对Collection中的所有元素进行聚合计算

[Random](#Random) 随机获取Collection中的元素

[Reverse](#Reverse) 将Collection数组进行转置

[Slice](#Slice) 获取Collection中的片段

[Search](#Search) 查找Collection中第一个匹配查询元素的下标

[Sort](#Sort) 将Collection中的元素进行升序排列输出

[SortDesc](#SortDesc) 将Collection中的元素按照降序排列输出

[Sum](#Sum) 返回Collection中的元素的和

[Shuffle](#Shuffle) 将Collection中的元素进行乱序排列

[SortBy](#SortBy) 根据对象数组中的某个元素进行Collection升序排列

[SortByDesc](#SortByDesc) 根据对象数组中的某个元素进行Collection降序排列

[ToInts](#ToInts) 将Collection变化为int数组

[ToInt64s](#ToInt64s) 将Collection变化为int64数组

[ToFloat64s](#ToFloat64s) 将Collection变化为float64数组

[ToFloat32s](#ToFloat32s) 将Collection变化为float32数组

[ToMixs](#ToMixs) 将Collection变化为Mix数组

[ToInterfaces](#ToInterfaces) 将collection变化为interface{}数组

[Unique](#Unique) 将Collection中重复的元素进行合并

### Append

`Append(item interface{}) ICollection`

Append挂载一个元素到当前Collection,如果挂载的元素类型不一致,则会在Collection中产生Error

```
intColl := NewIntCollection([]int{1,2})
intColl.Append(3)
if intColl.Err() == nil {
intColl.DD()
}

/*
IntCollection(3):{
0: 1
1: 2
2: 3
}
*/
```

### Avg

`Avg() IMix`

返回Collection的数值平均数,这里会进行类型降级,int,int64,float64的数值平均数都是返回float64类型。

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
mode, err := intColl.Avg().ToFloat64()
if err != nil {
t.Fatal(err.Error())
}
if mode != 2.0 {
t.Fatal("Avg error")
}
```

### Copy

Copy方法根据当前的数组,创造出一个同类型的数组,有相同的元素

```
func TestAbsCollection_Copy(t *testing.T) {
intColl := NewIntCollection([]int{1, 2})
intColl2 := intColl.Copy()
intColl2.DD()
if intColl2.Count() != 2 {
t.Fatal("Copy失败")
}
if reflect.TypeOf(intColl2) != reflect.TypeOf(intColl) {
t.Fatal("Copy类型失败")
}
}
```

### Contain

`Contains(obj interface{}) bool`

判断一个元素是否在Collection中,必须设置compare函数

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
if intColl.Contains(1) != true {
t.Fatal("contain 错误1")
}
if intColl.Contains(5) != false {
t.Fatal("contain 错误2")
}
```

### Diff

`Diff(arr ICollection) ICollection`

获取前一个Collection不在后一个Collection中的元素,必须设置compare函数

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
intColl2 := NewIntCollection([]int{2, 3, 4})

diff := intColl.Diff(intColl2)
diff.DD()
if diff.Count() != 1 {
t.Fatal("diff 错误")
}

/*
IntCollection(1):{
0: 1
}
*/
```

### DD

`DD()`

DD方法按照友好的格式展示Collection

```
a1 := Foo{A: "a1"}
a2 := Foo{A: "a2"}

objColl := NewObjCollection([]Foo{a1, a2})
objColl.DD()

/*
ObjCollection(2)(collection.Foo):{
0: {A:a1}
1: {A:a2}
}
*/

intColl := NewIntCollection([]int{1,2})
intColl.DD()

/*
IntCollection(2):{
0: 1
1: 2
}
*/
```

### Each

`Each(func(item interface{}, key int))`

对Collection中的每个函数都进行一次函数调用。传入的参数是回调函数。

如果希望在某次调用的时候中止,在此次调用的时候设置Collection的Error,就可以中止调用。

```go
intColl := NewIntCollection([]int{1, 2, 3, 4})
sum := 0
intColl.Each(func(item interface{}, key int) {
v := item.(int)
sum = sum + v
})

if intColl.Err() != nil {
t.Fatal(intColl.Err())
}

if sum != 10 {
t.Fatal("Each 错误")
}

sum = 0
intColl.Each(func(item interface{}, key int) {
v := item.(int)
sum = sum + v
if sum > 4 {
intColl.SetErr(errors.New("stop the cycle"))
return
}
})

if sum != 6 {
t.Fatal("Each 错误")
}

/*
PASS
*/
```

### Every

`Every(func(item interface{}, key int) bool) bool`

判断Collection中的每个元素是否都符合某个条件,只有当每个元素都符合条件,才整体返回true,否则返回false。

```go
intColl := NewIntCollection([]int{1, 2, 3, 4})
if intColl.Every(func(item interface{}, key int) bool {
i := item.(int)
return i > 1
}) != false {
t.Fatal("Every错误")
}

if intColl.Every(func(item interface{}, key int) bool {
i := item.(int)
return i > 0
}) != true {
t.Fatal("Every错误")
}
```

### ForPage

`ForPage(page int, perPage int) ICollection`

将Collection函数进行分页,按照每页第二个参数的个数,获取第一个参数的页数数据。

```go
intColl := NewIntCollection([]int{1, 2, 3, 4, 5, 6})
ret := intColl.ForPage(1, 2)
ret.DD()

if ret.Count() != 2 {
t.Fatal("For page错误")
}

/*
IntCollection(2):{
0: 3
1: 4
}
*/
```

### Filter

`Filter(func(item interface{}, key int) bool) ICollection`

根据过滤函数获取Collection过滤后的元素。

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
intColl.Filter(func(obj interface{}, index int) bool {
val := obj.(int)
if val == 2 {
return true
}
return false
}).DD()

/*
IntCollection(2):{
0: 2
1: 2
}
*/
```

### First

`First(...func(item interface{}, key int) bool) IMix`

获取符合过滤条件的第一个元素,如果没有填写过滤函数,返回第一个元素。

注:只能传递0个或者1个过滤函数,如果传递超过1个过滤函数,只有第一个过滤函数起作用

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
intColl.First(func(obj interface{}, index int) bool {
val := obj.(int)
if val > 2 {
return true
}
return false
}).DD()

/*
IMix(int): 3
*/

```

```
func TestIntCollection_Filter(t *testing.T) {
intColl := NewIntCollection([]int{1,2,3})
a, err := intColl.First().ToInt()
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(a, 1) {
t.Fatal("filter error")
}
}
```

### Index

`Index(i int) IMix`

Index获取元素中的第几个元素,下标从0开始,如果i超出了长度,则Collection记录错误。

```
intColl := NewIntCollection([]int{1,2})
foo := intColl.Index(1)
foo.DD()

/*
IMix(int): 2
*/
```

### IsEmpty

`IsEmpty() bool`

判断一个Collection是否为空,为空返回true, 否则返回false

```go
intColl := NewIntCollection([]int{1,2})
println(intColl.IsEmpty()) // false
```

### IsNotEmpty

`IsNotEmpty() bool`

判断一个Collection是否为空,为空返回false,否则返回true
```go
intColl := NewIntCollection([]int{1,2})
println(intColl.IsNotEmpty()) // true
```

### Join

`Join(split string, format ...func(item interface{}) string) string`

将Collection中的元素按照某种方式聚合成字符串。该函数接受一个或者两个参数,第一个参数是聚合字符串的分隔符号,第二个参数是聚合时候每个元素的格式化函数,如果没有设置第二个参数,则使用`fmt.Sprintf("%v")`来该格式化

```go
intColl := NewIntCollection([]int{2, 4, 3})
out := intColl.Join(",")
if out != "2,4,3" {
t.Fatal("join错误")
}
out = intColl.Join(",", func(item interface{}) string {
return fmt.Sprintf("'%d'", item.(int))
})
if out != "'2','4','3'" {
t.Fatal("join 错误")
}
```

### Last

`Last(...func(item interface{}, key int) bool) IMix`

获取该Collection中满足过滤的最后一个元素,如果没有填写过滤条件,默认返回最后一个元素

```go
intColl := NewIntCollection([]int{1, 2, 3, 4, 3, 2})
last, err := intColl.Last().ToInt()
if err != nil {
t.Fatal("last get error")
}
if last != 2 {
t.Fatal("last 获取错误")
}

last, err = intColl.Last(func(item interface{}, key int) bool {
i := item.(int)
return i > 2
}).ToInt()

if err != nil {
t.Fatal("last get error")
}
if last != 3 {
t.Fatal("last 获取错误")
}
```

### Merge

`Merge(arr ICollection) ICollection`

将两个Collection的元素进行合并,这个函数会修改原Collection。

```go
intColl := NewIntCollection([]int{1, 2 })

intColl2 := NewIntCollection([]int{3, 4})

intColl.Merge(intColl2)

if intColl.Err() != nil {
t.Fatal(intColl.Err())
}

if intColl.Count() != 4 {
t.Fatal("Merge 错误")
}

intColl.DD()

/*
IntCollection(4):{
0: 1
1: 2
2: 3
3: 4
}
*/
```

### Map

`Map(func(item interface{}, key int) interface{}) ICollection`

对Collection中的每个函数都进行一次函数调用,并将返回值组装成ICollection

这个回调函数形如: `func(item interface{}, key int) interface{}`

如果希望在某此调用的时候中止,就在此次调用的时候设置Collection的Error,就可以中止,且此次回调函数生成的结构不合并到最终生成的ICollection。

```go
intColl := NewIntCollection([]int{1, 2, 3, 4})
newIntColl := intColl.Map(func(item interface{}, key int) interface{} {
v := item.(int)
return v * 2
})
newIntColl.DD()

if newIntColl.Count() != 4 {
t.Fatal("Map错误")
}

newIntColl2 := intColl.Map(func(item interface{}, key int) interface{} {
v := item.(int)

if key > 2 {
intColl.SetErr(errors.New("break"))
return nil
}

return v * 2
})
newIntColl2.DD()

/*
IntCollection(4):{
0: 2
1: 4
2: 6
3: 8
}
IntCollection(3):{
0: 2
1: 4
2: 6
}
*/
```

### Mode

`Mode() IMix`

获取Collection中的众数,如果有大于两个的众数,返回第一次出现的那个。

```go
intColl := NewIntCollection([]int{1, 2, 2, 3, 4, 5, 6})
mode, err := intColl.Mode().ToInt()
if err != nil {
t.Fatal(err.Error())
}
if mode != 2 {
t.Fatal("Mode error")
}

intColl = NewIntCollection([]int{1, 2, 2, 3, 4, 4, 5, 6})

mode, err = intColl.Mode().ToInt()
if err != nil {
t.Fatal(err.Error())
}
if mode != 2 {
t.Fatal("Mode error")
}
```

### Max

`Max() IMix`

获取Collection中的最大元素,必须设置compare函数

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
max, err := intColl.Max().ToInt()
if err != nil {
t.Fatal(err)
}

if max != 3 {
t.Fatal("max错误")
}

```

### Min

`Min() IMix`

获取Collection中的最小元素,必须设置compare函数

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
min, err := intColl.Min().ToInt()
if err != nil {
t.Fatal(err)
}

if min != 1 {
t.Fatal("min错误")
}

```

### Median

`Median() IMix`

获取Collection的中位数,如果Collection个数是单数,返回排序后中间的元素,如果Collection的个数是双数,返回排序后中间两个元素的算数平均数。

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
median, err := intColl.Median().ToFloat64()
if err != nil {
t.Fatal(err)
}

if median != 2.0 {
t.Fatal("Median 错误" + fmt.Sprintf("%v", median))
}
```

### NewEmpty

`NewEmpty(err ...error) ICollection`

NewEmpty方法根据当前的数组,创造出一个同类型的数组,但长度为0

```
intColl := NewIntCollection([]int{1,2})
intColl2 := intColl.NewEmpty()
intColl2.DD()

/*
IntCollection(0):{
}
*/
```

### Nth

`Nth(n int, offset int) ICollection`

Nth(n int, offset int) 获取从offset偏移量开始的每第n个,偏移量offset的设置为第一个。

```go
intColl := NewIntCollection([]int{1, 2, 3, 4, 5, 6})
ret := intColl.Nth(4, 1)
ret.DD()

if ret.Count() != 2 {
t.Fatal("Nth 错误")
}

/*
IntCollection(2):{
0: 2
1: 6
}
*/
```

### Pad

`Pad(start int, def interface{}) ICollection`

填充Collection数组,如果第一个参数大于0,则代表往Collection的右边进行填充,如果第一个参数小于零,则代表往Collection的左边进行填充。

```go
intColl := NewIntCollection([]int{1, 2, 3})
ret := intColl.Pad(5, 0)
if ret.Err() != nil {
t.Fatal(ret.Err().Error())
}

ret.DD()
if ret.Count() != 5 {
t.Fatal("Pad 错误")
}

ret = intColl.Pad(-5, 0)
if ret.Err() != nil {
t.Fatal(ret.Err().Error())
}
ret.DD()
if ret.Count() != 5 {
t.Fatal("Pad 错误")
}

/*
IntCollection(5):{
0: 1
1: 2
2: 3
3: 0
4: 0
}
IntCollection(5):{
0: 0
1: 0
2: 1
3: 2
4: 3
}
*/
```

### Pop

`Pop() IMix`

从Collection右侧弹出一个元素

```go
intColl := NewIntCollection([]int{1, 2, 3, 4, 5, 6})
pop := intColl.Pop()
in, err := pop.ToInt()
if err != nil {
t.Fatal(err.Error())
}
if in != 6 {
t.Fatal("Pop 错误")
}
intColl.DD()
if intColl.Count() != 5 {
t.Fatal("Pop 后本体错误")
}

/*
IntCollection(5):{
0: 1
1: 2
2: 3
3: 4
4: 5
}
*/
```

### Push

`Push(item interface{}) ICollection`

往Collection的右侧推入一个元素

```go
intColl := NewIntCollection([]int{1, 2, 3, 4, 5, 6})
intColl.Push(7)
intColl.DD()
if intColl.Count() != 7 {
t.Fatal("Push 后本体错误")
}

/*
IntCollection(7):{
0: 1
1: 2
2: 3
3: 4
4: 5
5: 6
6: 7
}
*/
```

### Prepend

`Prepend(item interface{}) ICollection`

往Collection左侧加入元素

```go
intColl := NewIntCollection([]int{1, 2, 3, 4, 5, 6})
intColl.Prepend(0)
if intColl.Err() != nil {
t.Fatal(intColl.Err().Error())
}

intColl.DD()
if intColl.Count() != 7 {
t.Fatal("Prepend错误")
}

/*
IntCollection(7):{
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
}
*/
```

### Pluck

`Pluck(key string) ICollection`

将对象数组中的某个元素提取出来组成一个新的Collection。这个元素必须是Public元素

注:这个函数只对ObjCollection生效。

```go
type Foo struct {
A string
}

func TestObjCollection_Pluck(t *testing.T) {
a1 := Foo{A: "a1"}
a2 := Foo{A: "a2"}

objColl := NewObjCollection([]Foo{a1, a2})

objColl.Pluck("A").DD()
}

/*
StrCollection(2):{
0: a1
1: a2
}
*/
```

### Reject

`Reject(func(item interface{}, key int) bool) ICollection`

将满足过滤条件的元素删除

```go
intColl := NewIntCollection([]int{1, 2, 3, 4, 5})
retColl := intColl.Reject(func(item interface{}, key int) bool {
i := item.(int)
return i > 3
})
if retColl.Count() != 3 {
t.Fatal("Reject 重复错误")
}

retColl.DD()

/*
IntCollection(3):{
0: 1
1: 2
2: 3
}
*/
```

### Reduce

`Reduce(func(carry IMix, item IMix) IMix) IMix`

对Collection中的所有元素进行聚合计算。

如果希望在某次调用的时候中止,在此次调用的时候设置Collection的Error,就可以中止调用。

```go
intColl := NewIntCollection([]int{1, 2, 3, 4})
sumMix := intColl.Reduce(func(carry IMix, item IMix) IMix {
carryInt, _ := carry.ToInt()
itemInt, _ := item.ToInt()
return NewMix(carryInt + itemInt)
})

sumMix.DD()

sum, err := sumMix.ToInt()
if err != nil {
t.Fatal(err.Error())
}
if sum != 10 {
t.Fatal("Reduce计算错误")
}

/*
IMix(int): 10
*/
```

### Random

`Random() IMix`

随机获取Collection中的元素,随机数种子使用时间戳

```go
intColl := NewIntCollection([]int{1, 2, 3, 4, 5, 6})
out := intColl.Random()
out.DD()

_, err := out.ToInt()
if err != nil {
t.Fatal(err.Error())
}

/*
IMix(int): 5
*/
```

### Reverse

`Reverse() ICollection`

将Collection数组进行转置

```go
intColl := NewIntCollection([]int{1, 2, 3, 4, 5, 6})
vs := intColl.Reverse()
vs.DD()

/*
IntCollection(6):{
0: 6
1: 5
2: 4
3: 3
4: 2
5: 1
}
*/
```

### Search

`Search(item interface{}) int`

查找Collection中第一个匹配查询元素的下标,如果存在,返回下标;如果不存在,返回-1

*注意* 此函数要求设置compare方法,基础元素数组(int, int64, float32, float64, string)可直接调用!

```go
intColl := NewIntCollection([]int{1,2})
if intColl.Search(2) != 1 {
t.Fatal("Search 错误")
}

intColl = NewIntCollection([]int{1,2, 3, 3, 2})
if intColl.Search(3) != 2 {
t.Fatal("Search 重复错误")
}
```

### Slice

`Slice(...int) ICollection`

获取Collection中的片段,可以有两个参数或者一个参数。

如果是两个参数,第一个参数代表开始下标,第二个参数代表结束下标,当第二个参数为-1时候,就代表到Collection结束。

如果是一个参数,则代表从这个开始下标一直获取到Collection结束的片段。

```go
intColl := NewIntCollection([]int{1, 2, 3, 4, 5})
retColl := intColl.Slice(2)
if retColl.Count() != 3 {
t.Fatal("Slice 错误")
}

retColl.DD()

retColl = intColl.Slice(2,2)
if retColl.Count() != 2 {
t.Fatal("Slice 两个参数错误")
}

retColl.DD()

retColl = intColl.Slice(2, -1)
if retColl.Count() != 3 {
t.Fatal("Slice第二个参数为-1错误")
}

retColl.DD()

/*
IntCollection(3):{
0: 3
1: 4
2: 5
}
IntCollection(2):{
0: 3
1: 4
}
IntCollection(3):{
0: 3
1: 4
2: 5
}
*/

```

### Shuffle

`Shuffle() ICollection`

将Collection中的元素进行乱序排列,随机数种子使用时间戳

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
newColl := intColl.Shuffle()
newColl.DD()
if newColl.Err() != nil {
t.Fatal(newColl.Err())
}

/*
IntCollection(4):{
0: 1
1: 3
2: 2
3: 2
}
*/
```

### Sort

`Sort() ICollection`

将Collection中的元素进行升序排列输出,必须设置compare函数

```go
intColl := NewIntCollection([]int{2, 4, 3})
intColl2 := intColl.Sort()
if intColl2.Err() != nil {
t.Fatal(intColl2.Err())
}
intColl2.DD()

/*
IntCollection(3):{
0: 2
1: 3
2: 4
}
*/
```

### SortDesc

`SortDesc() ICollection`

将Collection中的元素按照降序排列输出,必须设置compare函数

```go
intColl := NewIntCollection([]int{2, 4, 3})
intColl2 := intColl.SortDesc()
if intColl2.Err() != nil {
t.Fatal(intColl2.Err())
}
intColl2.DD()

/*
IntCollection(3):{
0: 4
1: 3
2: 2
}
*/
```

### Sum

`Sum() IMix`

返回Collection中的元素的和

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
intColl.Sum().DD()
sum, err := intColl.Sum().ToInt()
if err != nil {
t.Fatal(err)
}

if sum != 8 {
t.Fatal("sum 错误")
}

/*
IMix(int): 8
*/
```

### SortBy

`SortBy(key string) ICollection`

根据对象数组中的某个元素进行Collection升序排列。这个元素必须是Public元素

注:这个函数只对ObjCollection生效。这个对象数组的某个元素必须是基础类型。

```go
type Foo struct {
A string
B int
}

func TestObjCollection_SortBy(t *testing.T) {
a1 := Foo{A: "a1", B: 3}
a2 := Foo{A: "a2", B: 2}

objColl := NewObjCollection([]Foo{a1, a2})

newObjColl := objColl.SortBy("B")

newObjColl.DD()

obj, err := newObjColl.Index(0).ToInterface()
if err != nil {
t.Fatal(err)
}

foo := obj.(Foo)
if foo.B != 2 {
t.Fatal("SortBy error")
}
}

/*
ObjCollection(2)(collection.Foo):{
0: {A:a2 B:2}
1: {A:a1 B:3}
}
*/
```

### SortByDesc

`SortByDesc(key string) ICollection`

根据对象数组中的某个元素进行Collection降序排列。这个元素必须是Public元素

注:这个函数只对ObjCollection生效。这个对象数组的某个元素必须是基础类型。

```go
type Foo struct {
A string
B int
}

func TestObjCollection_SortByDesc(t *testing.T) {
a1 := Foo{A: "a1", B: 2}
a2 := Foo{A: "a2", B: 3}

objColl := NewObjCollection([]Foo{a1, a2})

newObjColl := objColl.SortByDesc("B")

newObjColl.DD()

obj, err := newObjColl.Index(0).ToInterface()
if err != nil {
t.Fatal(err)
}

foo := obj.(Foo)
if foo.B != 3 {
t.Fatal("SortBy error")
}
}

/*
ObjCollection(2)(collection.Foo):{
0: {A:a2 B:3}
1: {A:a1 B:2}
}
*/
```

------------

### ToInts

`ToInts() ([]int, error)`

将Collection变化为int数组,如果Collection内的元素类型不符合,或者Collection有错误,则返回错误。

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
arr, err := intColl.ToInts()
if err != nil {
t.Fatal(err)
}
if len(arr) != 4 {
t.Fatal(errors.New("ToInts error"))
}
```

### ToInt64s

`ToInt64s() ([]int64, error)`

将Collection变化为int64数组,如果Collection内的元素类型不符合,或者Collection有错误,则返回错误。

```go
intColl := NewInt64Collection([]int{1, 2, 2, 3})
arr, err := intColl.ToInts()
if err != nil {
t.Fatal(err)
}
if len(arr) != 4 {
t.Fatal(errors.New("ToInts error"))
}
```

### ToFloat64s

`ToFloat64s() ([]float64, error)`

将Collection变化为float64数组,如果Collection内的元素类型不符合,或者Collection有错误,则返回错误。

```go
arr := NewFloat64Collection([]float64{1.0 ,2.0,3.0,4.0,5.0})

arr.DD()

max, err := arr.Max().ToFloat64()
if err != nil {
t.Fatal(err)
}

if max != 5 {
t.Fatal(errors.New("max error"))
}

arr2 := arr.Filter(func(obj interface{}, index int) bool {
val := obj.(float64)
if val > 2.0 {
return true
}
return false
})
if arr2.Count() != 3 {
t.Fatal(errors.New("filter error"))
}

out, err := arr2.ToFloat64s()
if err != nil || len(out) != 3 {
t.Fatal(errors.New("to float64s error"))
}

```

### ToFloat32s

`ToFloat32s() ([]float32, error)`

将Collection变化为float32数组,如果Collection内的元素类型不符合,或者Collection有错误,则返回错误。

```go
arr := NewFloat32Collection([]float32{1.0 ,2.0,3.0,4.0,5.0})

arr.DD()

max, err := arr.Max().ToFloat32()
if err != nil {
t.Fatal(err)
}

if max != 5 {
t.Fatal(errors.New("max error"))
}

arr2 := arr.Filter(func(obj interface{}, index int) bool {
val := obj.(float32)
if val > 2.0 {
return true
}
return false
})
if arr2.Count() != 3 {
t.Fatal(errors.New("filter error"))
}

out, err := arr2.ToFloat32s()
if err != nil || len(out) != 3 {
t.Fatal(errors.New("to float32s error"))
}
```

### ToMixs

`ToMixs() ([]IMix, error)`

将Collection变化为Mix数组,如果Collection内的元素类型不符合,或者Collection有错误,则返回错误

```go
intColl := NewIntCollection([]int{1, 2, 2, 3})
arr, err := intColl.ToMixs()
if err != nil {
t.Fatal(err)
}
if len(arr) != 4 {
t.Fatal(errors.New("ToInts error"))
}
```

### ToInterfaces

`ToInterfaces() ([]interface{}, error)`

将Collection变化为Interface{}数组,如果Collection内的元素类型不符合,或者Collection有错误,则返回错误

### Unique

`Unique() ICollection`

将Collection中重复的元素进行合并,返回唯一的一个数组。

*注意* 此函数要求设置compare方法,基础元素数组(int, int64, float32, float64, string)可直接调用!

```go
intColl := NewIntCollection([]int{1,2, 3, 3, 2})
uniqColl := intColl.Unique()
if uniqColl.Count() != 3 {
t.Fatal("Unique 重复错误")
}

uniqColl.DD()
/*
IntCollection(3):{
0: 1
1: 2
2: 3
}
*/
```

-------------
```
$ go test -bench=. -run=non

goos: darwin
goarch: amd64
pkg: github.com/jianfengye/collection
Benchmark_Append-12 3512688 387 ns/op
Benchmark_Contain-12 6727482 179 ns/op
Benchmark_Copy-12 7260177 159 ns/op
Benchmark_Diff-12 2310327 522 ns/op
Benchmark_Each-12 7784914 154 ns/op
Benchmark_Every-12 7602790 157 ns/op
Benchmark_ForPage-12 2355352 515 ns/op
Benchmark_Filter-12 1356804 876 ns/op
Benchmark_First-12 19379992 61.8 ns/op
Benchmark_Index-12 19259961 62.1 ns/op
Benchmark_IsEmpty-12 162860646 7.33 ns/op
Benchmark_IsNotEmpty-12 163036106 7.36 ns/op
Benchmark_Join-12 4705460 255 ns/op
Benchmark_Last-12 15544176 76.8 ns/op
Benchmark_Merge-12 1372609 872 ns/op
Benchmark_Map-12 2752177 439 ns/op
Benchmark_Max-12 3218686 372 ns/op
Benchmark_Min-12 3233270 372 ns/op
Benchmark_Median-12 1379985 869 ns/op
Benchmark_Nth-12 2360064 503 ns/op
Benchmark_Pop-12 1454916 834 ns/op
Benchmark_Push-12 3629934 346 ns/op
Benchmark_Prepend-12 10000 376298 ns/op
Benchmark_Pluck-12 2531895 469 ns/op
Benchmark_Reject-12 4184707 286 ns/op
Benchmark_Random-12 142698 8397 ns/op
Benchmark_Reverse-12 1324262 903 ns/op
Benchmark_Slice-12 2272142 515 ns/op
Benchmark_Search-12 6484984 186 ns/op
Benchmark_Sort-12 3627673 333 ns/op
Benchmark_SortDesc-12 3565390 331 ns/op
Benchmark_Shuffle-12 128826 9320 ns/op
Benchmark_SortBy-12 564669482 2.13 ns/op
Benchmark_SortByDesc-12 595491585 2.03 ns/op
Benchmark_Unique-12 1219267 979 ns/op
PASS
ok github.com/jianfengye/collection 59.484s
```

License
------------
`collection` is licensed under [Apache License](LICENSE).

## Contributors

This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].

## Backers

Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/collection#backer)]

## Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/collection#sponsor)]