Skip to content

Commit

Permalink
Merge pull request #21 from azihsoyn/feature/skip
Browse files Browse the repository at this point in the history
support skip
  • Loading branch information
azihsoyn committed Nov 29, 2016
2 parents ca5a256 + 2bf79b9 commit c91643b
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -14,6 +14,7 @@ gollection is golang collection util library (inspired by [kotlin collection](ht
- fold
- map
- reduce
- skip ([java8](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#skip-long-))
- sortBy
- take

Expand Down
11 changes: 11 additions & 0 deletions example_test.go
Expand Up @@ -80,6 +80,17 @@ func Example_reduce() {
// Output: 55 <nil>
}

func Example_skip() {
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

res, err := gollection.New(arr).Skip(3).Result()
fmt.Println(res, err)
res, err = gollection.New(arr).Skip(30).Result()
fmt.Println(res, err)
// Output: [4 5 6 7 8 9 10] <nil>
// [] <nil>
}

func Example_sort() {
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}

Expand Down
19 changes: 19 additions & 0 deletions examples/skip/main.go
@@ -0,0 +1,19 @@
package main

import (
"fmt"

"github.com/azihsoyn/gollection"
)

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

res, _ := gollection.New(arr).Skip(3).Result()
fmt.Println("origin : ", arr)
fmt.Println("ret : ", res) // {4, 5, 6, 7, 8, 9, 10}

res, _ = gollection.New(arr).Skip(30).Result()
fmt.Println("origin : ", arr)
fmt.Println("ret : ", res) // {}
}
80 changes: 80 additions & 0 deletions skip.go
@@ -0,0 +1,80 @@
package gollection

import (
"fmt"
"reflect"
)

func (g *gollection) Skip(n int) *gollection {
if g.err != nil {
return &gollection{err: g.err}
}

if g.ch != nil {
return g.skipStream(n)
}

return g.skip(n)
}

func (g *gollection) skip(n int) *gollection {
sv, err := g.validateSlice("Take")
if err != nil {
return &gollection{err: err}
}

if n < 0 {
return &gollection{err: fmt.Errorf("gollection.Skip called with invalid argument. should be larger than 0")}
}

limit := sv.Len()
start := n
if limit < start {
start = limit
}

ret := reflect.MakeSlice(sv.Type(), 0, limit-start)

for i := start; i < limit; i++ {
ret = reflect.Append(ret, sv.Index(i))
}

return &gollection{
slice: ret.Interface(),
}
}

func (g *gollection) skipStream(n int) *gollection {
next := &gollection{
ch: make(chan interface{}),
}

var initialized bool
go func() {
i := 0
for {
select {
case v, ok := <-g.ch:
// initialize next stream type
if ok && !initialized {
next.ch <- v
initialized = true
continue
}

if ok {
i++
if n < i {
next.ch <- v
}
} else {
close(next.ch)
return
}
default:
continue
}
}
}()
return next
}
74 changes: 74 additions & 0 deletions skip_test.go
@@ -0,0 +1,74 @@
package gollection_test

import (
"testing"
"time"

"github.com/azihsoyn/gollection"
"github.com/stretchr/testify/assert"
)

func TestSkip(t *testing.T) {
assert := assert.New(t)
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
expect := []int{4, 5, 6, 7, 8, 9, 10}

res, err := gollection.New(arr).Skip(3).Result()
assert.NoError(err)
assert.Equal(expect, res)

expect = []int{}
res, err = gollection.New(arr).Skip(30).Result()
assert.NoError(err)
assert.Equal(expect, res)
}

func TestSkip_NotSlice(t *testing.T) {
assert := assert.New(t)
_, err := gollection.New("not slice value").Skip(0).Result()
assert.Error(err)
}

func TestSkip_InvalidArgument(t *testing.T) {
assert := assert.New(t)
_, err := gollection.New([]int{1, 2, 3}).Skip(-1).Result()
assert.Error(err)
}

func TestSkip_HavingError(t *testing.T) {
assert := assert.New(t)
_, err := gollection.New("not slice value").Skip(0).Skip(0).Result()
assert.Error(err)
}

func TestSkip_Stream(t *testing.T) {
assert := assert.New(t)
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
expect := []int{4, 5, 6, 7, 8, 9, 10}

res, err := gollection.NewStream(arr).Skip(3).Result()
assert.NoError(err)
assert.Equal(expect, res)

expect = []int{}
res, err = gollection.NewStream(arr).Skip(30).Result()
assert.NoError(err)
assert.Equal(expect, res)

gollection.NewStream(arr).Filter(func(v int) bool {
time.Sleep(1)
return true
}).Skip(100)
}

func TestSkip_Stream_NotSlice(t *testing.T) {
assert := assert.New(t)
_, err := gollection.NewStream("not slice value").Skip(0).Result()
assert.Error(err)
}

func TestSkip_Stream_HavingError(t *testing.T) {
assert := assert.New(t)
_, err := gollection.NewStream("not slice value").Skip(0).Skip(0).Result()
assert.Error(err)
}

0 comments on commit c91643b

Please sign in to comment.