TL;DR
GoStream是个参考Java StreamAPI,基于go-linq实现的数据处理库。
它可以声明式地对数据进行转换、过滤、排序、分组、收集,而无需关心操作细节。
背景
项目中经常需要对数据进行分组、转换,已有的数据处理库go-linq、go-streams都无法满足我需求。API不友好、不支持多级分组… 所以想新写个Libary,于是,有了GoStream!!
示例
更完整的例子,请参考walkthrough.go
Base Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| input := []int{4, 3, 2, 1} want := []int{6, 8}
got := From(input).Map(func(it interface{}) interface{} { return 2 * it.(int) }).Filter(func(it interface{}) bool { return it.(int) > 5 }).SortedBy(func(it interface{}) interface{} { return it }).Collect(ToSlice([]int(nil)))
if !reflect.DeepEqual(got, want) { panic(fmt.Sprintf("%v != %v", got, want)) }
|
Map & FlatMap
Map和FlatMap的差别在于:FlatMap的mapper返回一个Stream,用于将多级数据打扁。
1 2 3 4 5 6 7
| input := [][]int{{3, 2, 1}, {6, 5, 4}, {9, 8, 7}} want := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} got := From(input).FlatMap(func(it interface{}) Stream { return From(it) }).SortedBy(func(it interface{}) interface{} { return it }).Collect(ToSlice([]int{}))
|
Collect ToSlice & ToMap
Collect将数据收集起来。受限于go的类型系统,需要显示传类型参数——一个目标类型的实例,可以为nil。
1 2 3 4 5 6 7
| intput := []int{1, 2, 3, 4, 5} identity := func(it interface{}) interface{} { return it }
gotSlice := From(intput).Collect(ToSlice([]int{}))
gotMap := From(intput).Collect(ToMap(map[int]int(nil), identity, identity))
|
Collect GroupBy
GroupBy定义一个分组收集器,参数依序分别为 类型参数、分类方法、下游收集器。
GroupBy可以和ToSlice、ToMap组合,GroupBy也可以多级嵌套,实现多级分组。
GroupBy(typ interface{}, classifier normalFn, downstream collector) collector
假设一组货物,需要按Status,Location进行分组,目标类型为 map[int]map[string][]*Cargo。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| type Cargo struct { ID int Name string Location string Status int }
input := []*Cargo{{ ID: 1, Name: "foo", Location: "shenzhen", Status: 1, }, { ID: 2, Name: "bar", Location: "shenzhen", Status: 0, }, { ID: 3, Name: "zhang", Location: "guangzhou", Status: 1, }}
getStatus := func(it interface{}) interface{} { return it.(*Cargo).Status } getLocation := func(it interface{}) interface{} { return it.(*Cargo).Location }
got := From(input).Collect( GroupBy(map[int]map[string][]*Cargo(nil), getStatus, GroupBy(map[string][]*Cargo(nil), getLocation, ToSlice([]*Cargo(nil)))))
|
Flatten Group
这个示例演示如何将多级分组Map扁平化。map[int]map[string][]*Cargo => []*Cargo
1 2 3 4 5
| From(cargoByLocationByTo).FlatMap(func(it interface{}) Stream { return From(it.(KeyValue).Value).FlatMap(func(it2 interface{}) Stream { return From(it2.(KeyValue).Value) }) }).Collect(ToSlice([]*Cargo{}))
|