koazee

A StreamLike, Immutable, Lazy Loading and smart Golang Library to deal with slices.

Github星跟蹤圖

Build Status
Go Report Card
godoc
codecov
Awesome

Koazee

Lazy like a koala, smart like a chimpanzee

What is Koazee?

Koazee is a StreamLike, Immutable, Lazy Loading and smart Golang Library to deal with slices.

Visit the Koazee wiki to find out what Koazee can do.

Koazee Highlights

  • Immutable: Koazee won't modify your inputs. 
  • StreamLike: We can combine operations up our convenience. 
  • Lazy loading: Operations are not performed until they're required
  • Generic: Koazee provides a generic interface able to deal with slice of any type without creating custom functions.
  • Focusing on performance: First rule for implementing a new operation is providing the best possible performance.

Getting started

Installing

Add Koazee to your project

Go modules

module github.com/me/project
require ( 
  github.com/wesovilabs/koazee vX.Y.Z
)

Glide

glide get github.com/wesovilabs/koazee

Go dep

go get github.com/wesovilabs/koazee

Usage

Stream creation

Let's first obtain a stream from an existing array.

package main

import (
	"fmt"
	"github.com/wesovilabs/koazee"
)

var numbers = []int{1, 5, 4, 3, 2, 7, 1, 8, 2, 3}

func main() {
	fmt.Printf("slice: %v\n", numbers)
	stream := koazee.StreamOf(numbers)
	fmt.Printf("stream: %v\n", stream.Out().Val())
}

/**
go run main.go

slice: [1 5 4 3 2 7 1 8 2 3]
stream: [1 5 4 3 2 7 1 8 2 3]
*/

Stream operations

Current release v0.0.3 (Gibbon) brings us 20 generic operations that are showed below

stream.At / stream.First / stream.Last

These operations return an element from the stream

package main

import (
	"fmt"
	"github.com/wesovilabs/koazee"
)

var numbers = []int{1, 5, 4, 3, 2, 7, 1, 8, 2, 3}

func main() {
	stream := koazee.StreamOf(numbers)
	fmt.Printf("stream.At(4): %d\n", stream.At(4).Int())
	fmt.Printf("stream.First: %d\n", stream.First().Int())
	fmt.Printf("stream.Last: %d\n", stream.Last().Int())
}

/**
go run main.go

stream.At(4): 2
stream.First: 1
stream.Last: 3
*/
stream.Add / stream.Drop / stream.DropWhile / stream.DeleteAt / stream.Pop / stream.Set

These operations add or delete elements from the stream.

package main

import (
	"fmt"
	"github.com/wesovilabs/koazee"
)

var numbers = []int{1, 5, 4, 3, 2, 7, 1, 8, 2, 3}

func main() {
	fmt.Printf("input: %v\n", numbers)

	stream := koazee.StreamOf(numbers)
	fmt.Print("stream.Add(10): ")
	fmt.Println(stream.Add(10).Do().Out().Val())

	fmt.Print("stream.Drop(5): ")
	fmt.Println(stream.Drop(5).Do().Out().Val())
	
	fmt.Print("stream.DropWhile(val<=5): ")
	fmt.Println(stream.DropWhile(func(element int)bool{return element<=5}).Do().Out().Val())

	fmt.Print("stream.DeleteAt(4): ")
	fmt.Println(stream.DeleteAt(4).Do().Out().Val())

	fmt.Print("stream.Set(0,5): ")
	fmt.Println(stream.Set(0, 5).Do().Out().Val())

	fmt.Print("stream.Pop(): ")
	val, newStream := stream.Pop()
	fmt.Printf("%d ... ", val.Int())
	fmt.Println(newStream.Out().Val())

}

/**
go run main.go

input: [1 5 4 3 2 7 1 8 2 3]
stream.Add(10): [1 5 4 3 2 7 1 8 2 3 10]
stream.Drop(5): [1 4 3 2 7 1 8 2 3]
stream.DropWhile(val<=5): [7 8]
stream.DeleteAt(4): [1 5 4 3 7 1 8 2 3]
stream.Set(0,5): [5 5 4 3 2 7 1 8 2 3]
stream.Pop(): 1 ... [5 4 3 2 7 1 8 2 3]
*/
tream.Count / stream.IndexOf / stream.IndexesOf / stream.LastIndexOf / stream.Contains

These operations return info from the elements in the stream

package main

import (
	"fmt"
	"github.com/wesovilabs/koazee"
)

var numbers = []int{1, 5, 4, 3, 2, 7, 1, 8, 2, 3}

func main() {
	fmt.Printf("input: %v\n", numbers)
	stream := koazee.StreamOf(numbers)
	count, _ := stream.Count()
	fmt.Printf("stream.Count(): %d\n", count)
	index, _ := stream.IndexOf(2)
	fmt.Printf("stream.IndexOf(2): %d\n", index)
	indexes, _ := stream.IndexesOf(2)
    fmt.Printf("stream.IndexesOf(2): %d\n", indexes)
	index, _ = stream.LastIndexOf(2)
	fmt.Printf("stream.LastIndexOf(2): %d\n", index)
	contains, _ := stream.Contains(7)
	fmt.Printf("stream.Contains(7): %v\n", contains)
}

/**
go run main.go

input: [1 5 4 3 2 7 1 8 2 3]
stream.Count(): 10
stream.IndexOf(2): 4
stream.IndexesOf(2): [4 8]
stream.LastIndexOf(2): 8
stream.Contains(7): true
*/
stream.Sort / stream.Reverse

These operations organize the elements in the stream.

package main

import (
	"fmt"
	"github.com/wesovilabs/koazee"
	"strings"
)

var animals = []string{"lynx", "dog", "cat", "monkey", "fox", "tiger", "lion"}

func main() {
	fmt.Print("input: ")
	fmt.Println(animals)
	stream := koazee.StreamOf(animals)

	fmt.Print("stream.Reverse(): ")
	fmt.Println(stream.Reverse().Out().Val())

	fmt.Print("stream.Sort(strings.Compare): ")
	fmt.Println(stream.Sort(strings.Compare).Out().Val())

}

/**
go run main.go

input: [lynx dog cat monkey fox tiger lion]
stream.Reverse(): [lion tiger fox monkey cat dog lynx]
stream.Sort(strings.Compare): [cat dog fox lion lynx monkey tiger]
*/
stream.Take / stream.Filter / stream.RemoveDuplicates

These operations return a filtered stream.

package main

import (
	"fmt"
	"github.com/wesovilabs/koazee"
)

var animals = []string{"lynx", "dog", "cat", "monkey", "dog", "fox", "tiger", "lion"}

func main() {
	fmt.Print("input: ")
	fmt.Println(animals)
	stream := koazee.StreamOf(animals)

	fmt.Print("stream.Take(1,4): ")
	fmt.Println(stream.Take(1, 4).Out().Val())

	fmt.Print("stream.Filter(len==4): ")
	fmt.Println(stream.
		Filter(
			func(val string) bool {
				return len(val) == 4
			}).
		Out().Val(),
	)
	fmt.Print("stream.RemoveDuplicates(): ")
	fmt.Println(stream.RemoveDuplicates().Out().Val())
}

/**
go run main.go

input: [lynx dog cat monkey dog fox tiger lion]
stream.Take(1,4): [dog cat monkey dog]
stream.Filter(len==4): [lynx lion]
stream.RemoveDuplicates(): [lynx dog cat monkey fox tiger lion]
*/
stream.GroupBy

This operation creates groups depending on the returned function value

You can now optionally return an error as the second parameter to stop processing of the stream. The error will be available in stream.Out().Err().UserError().

package main

import (
	"fmt"
	"github.com/wesovilabs/koazee"
	"strings"
)

var animals = []string{"lynx", "dog", "cat", "monkey", "dog", "fox", "tiger", "lion"}

func main() {
	fmt.Printf("input: %v\n", animals)
	stream := koazee.StreamOf(animals)
	fmt.Print("stream.GroupBy(strings.Len): ")
	out, _ := stream.GroupBy(func(val string)int{return len(val)})
	fmt.Println(out)
}

/**
go run main.go

input: [lynx dog cat monkey dog fox tiger lion]
stream.GroupBy(strings.Len): map[5:[tiger] 4:[lynx lion] 3:[dog cat dog fox] 6:[monkey]]
*/
stream.Map

This operation performs a modification over all the elements in the stream.

You can now optionally return an error as the second parameter to stop processing of the stream. The error will be available in stream.Out().Err().UserError().

package main

import (
	"fmt"
	"github.com/wesovilabs/koazee"
	"strings"
)

var animals = []string{"lynx", "dog", "cat", "monkey", "dog", "fox", "tiger", "lion"}

func main() {
	fmt.Printf("input: %v\n", animals)
	stream := koazee.StreamOf(animals)
	fmt.Print("stream.Map(strings.Title): ")
	fmt.Println(stream.Map(strings.Title).Do().Out().Val())
}

/**
go run main.go

input: [lynx dog cat monkey dog fox tiger lion]
stream.Map(strings.Title): [Lynx Dog Cat Monkey Dog Fox Tiger Lion]
*/
stream.Reduce

This operation give us a single output after iterating over the elements in the stream.

You can now optionally return an error as the second parameter to stop processing of the stream. The error will be available in stream.Out().Err().UserError().

package main

import (
	"fmt"
	"github.com/wesovilabs/koazee"
)

var numbers = []int{1, 5, 4, 3, 2, 7, 1, 8, 2, 3}

func main() {
	fmt.Printf("input: %v\n", numbers)
	stream := koazee.StreamOf(numbers)
	fmt.Print("stream.Reduce(sum): ")
	fmt.Println(stream.Reduce(func(acc, val int) int {
		return acc + val
	}).Int())
}

/**
go run main.go

input: [1 5 4 3 2 7 1 8 2 3]
stream.Reduce(sum): 36
*/
stream.ForEach

This operation iterates over the element in the stream.

You can now optionally return an error as the second parameter to stop processing of the stream. The error will be available in stream.Out().Err().UserError().

package main

import (
	"fmt"
	"github.com/wesovilabs/koazee"
)

type message struct {
	user    string
	message string
}

var messages = []*message{
	{user: "John", message: "Hello Jane"},
	{user: "Jane", message: "Hey John, how are you?"},
	{user: "John", message: "I'm fine! and you?"},
	{user: "Jane", message: "Me too"},
}

func main() {

	stream := koazee.StreamOf(messages)
	stream.ForEach(func(m *message) {
		fmt.Printf("%s: \"%s\"\n", m.user, m.message)
	}).Do()
}

/**
go run main.go

John: "Hello Jane"
Jane: "Hey John, how are you?"
John: "I'm fine! and you?"
Jane: "Me too"
*/

Combine operations and evaluate them lazily

The main goal of Koazee is providing a set of operations that can be combined and being evaluated lazily.

package main

import (
	"fmt"
	"github.com/wesovilabs/koazee"
	"strings"
)

type Person struct {
	Name string
	Male bool
	Age  int
}

var people = []*Person{
	{"John Smith", true, 32},
	{"Peter Pan", true, 17},
	{"Jane Doe", false, 20},
	{"Anna Wallace", false, 35},
	{"Tim O'Brian", true, 13},
	{"Celia Hills", false, 15},
}

func main() {
	stream := koazee.
		StreamOf(people).
		Filter(func(person *Person) bool {
			return !person.Male
		}).
		Sort(func(person, otherPerson *Person) int {
			return strings.Compare(person.Name, otherPerson.Name)
		}).
		ForEach(func(person *Person) {
			fmt.Printf("%s is %d years old\n", person.Name, person.Age)
		})

	fmt.Println("Operations are not evaluated until we perform stream.Do()\n")
	stream.Do()
}

/**
go run main.go

Operations are not evaluated until we perform stream.Do()

Anna Wallace is 35 years old
Celia Hills is 15 years old
Jane Doe is 20 years old
 */

Available Operations, Operation, Description, Since, ---, ---, ---, Add, It adds a new element in the last position, v0.0.1, At, It returns the element in the given position, v0.0.1, Contains, It checks if the given element is found in the stream., v0.0.1, Count, It returns the number of elements in a stream, v0.0.1, DeleteAt, It remove the elements in the given position, v0.0.3, Drop, It removes an element from the stream, v0.0.1, DropWhile, It removes the elements in the stream that match with the given input function, v0.0.4, Filter, It discards those elements that doesn't match with the provided filter, v0.0.1, First, It returns the element in the first position, v0.0.1, ForEach, It does something over all the elements in the stream., v0.0.1, GroupBy, It creates groups depending on the returned function value, v0.0.4, IndexOf, It returns the first index of the element in the stream., v0.0.3, IndexesOf, It returns the index for all the occurrences of the element in the stream., v0.0.4, Last, It returns the element in the last position, v0.0.1, LastIndexOf, It returns the last occurrence for the element in the stream., v0.0.3, Map, It converts the element in the stream, v0.0.1, Pop, It extracts the first element in the stream and return this and the new stream, v0.0.3, Reduce, It reduceshe stream to a single value by executing a provided function for each value of the stream, v0.0.1, RemoveDuplicates, It removes duplicated elements., v0.0.1, Reverse, It reverses the sequence of elements in the stream., v0.0.3, Set, It replaces the element in the given index by the provided value, v0.0.3, Sort, It sorts the elements in the stream, v0.0.1, Take, It returns a stream with the elements between the given indexes, v0.0.3, ## Samples

A rich and growing set of examples can be found on koazee-samples

Benchmark

You can check the Benchmark for the Koazee operations here

A benchmark comparison with other frameworks can be found in Koazee vs Go-Funk vs Go-Linq

Guides & Tutorials

Shopping cart with Koazee

Roadmap

This is only the beginning! By the way, If you missed any operation in Koazee v0.0.3, or you found a bug, please create a new issue on Github or vote the existing ones!

Contributors

主要指標

概覽
名稱與所有者wesovilabs/koazee
主編程語言Go
編程語言Makefile (語言數: 2)
平台
許可證MIT License
所有者活动
創建於2018-11-09 09:49:19
推送於2020-11-18 17:04:42
最后一次提交2019-11-04 07:32:15
發布數7
最新版本名稱v0.0.5 (發布於 )
第一版名稱0.0.1 (發布於 )
用户参与
星數528
關注者數11
派生數31
提交數178
已啟用問題?
問題數41
打開的問題數14
拉請求數17
打開的拉請求數0
關閉的拉請求數5
项目设置
已啟用Wiki?
已存檔?
是復刻?
已鎖定?
是鏡像?
是私有?