Skip to content

Commit

Permalink
support distinct
Browse files Browse the repository at this point in the history
  • Loading branch information
azihsoyn committed Oct 27, 2016
1 parent 1b250cb commit 84ac45b
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
gollection is golang collection util library (inspired by [kotlin collection](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/index.html))

# supported functions
- distinct
- filter
- flatMap
- flatten
Expand Down
32 changes: 31 additions & 1 deletion distinct.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func (g *gollection) Distinct() *gollection {
if sv.Kind() != reflect.Slice {
return &gollection{
slice: nil,
err: fmt.Errorf("gollection.Take called with non-slice value of type %T", g.slice),
err: fmt.Errorf("gollection.Distinct called with non-slice value of type %T", g.slice),
}
}

Expand All @@ -33,3 +33,33 @@ func (g *gollection) Distinct() *gollection {
slice: ret.Interface(),
}
}

func (g *gollection) DistinctBy(f func(v interface{}) interface{}) *gollection {
if g.err != nil {
return &gollection{err: g.err}
}

sv := reflect.ValueOf(g.slice)
if sv.Kind() != reflect.Slice {
return &gollection{
slice: nil,
err: fmt.Errorf("gollection.DistinctBy called with non-slice value of type %T", g.slice),
}
}

ret := reflect.MakeSlice(sv.Type(), 0, sv.Len())
m := make(map[interface{}]bool)

for i := 0; i < sv.Len(); i++ {
v := sv.Index(i)
id := f(v.Interface())
if _, ok := m[id]; !ok {
ret = reflect.Append(ret, v)
m[id] = true
}
}

return &gollection{
slice: ret.Interface(),
}
}
28 changes: 28 additions & 0 deletions distinct_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,31 @@ func TestDistinct_HavingError(t *testing.T) {
_, err := gollection.New("not slice value").Distinct().Distinct().Result()
assert.Error(err)
}

func TestDistinctBy(t *testing.T) {
assert := assert.New(t)
arr := []string{"aaa", "bb", "c", "ddd", "ee", "f"}
expect := []string{"aaa", "bb", "c"}

res, err := gollection.New(arr).DistinctBy(func(v interface{}) interface{} {
return len(v.(string))
}).Result()
assert.NoError(err)
assert.Equal(expect, res)
}

func TestDistinctBy_NotSlice(t *testing.T) {
assert := assert.New(t)
_, err := gollection.New("not slice value").DistinctBy(func(v interface{}) interface{} {
return v
}).Result()
assert.Error(err)
}

func TestDistinctBy_HavingError(t *testing.T) {
assert := assert.New(t)
_, err := gollection.New("not slice value").DistinctBy(func(v interface{}) interface{} {
return v
}).Distinct().Result()
assert.Error(err)
}
19 changes: 19 additions & 0 deletions examples/distinct/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,23 @@ func main() {
res, _ := gollection.New(arr).Distinct().Result()
fmt.Println("origin : ", arr)
fmt.Println("ret : ", res) // {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

type user struct {
ID int64
Name string
}
users := []user{
{ID: 1, Name: "Ann"},
{ID: 2, Name: "Bob"},
{ID: 3, Name: "Charles"},
{ID: 4, Name: "Ann"},
{ID: 5, Name: "Bob"},
{ID: 6, Name: "Charles"},
}

res, _ = gollection.New(users).DistinctBy(func(v interface{}) interface{} {
return v.(user).Name
}).Result()
fmt.Println("origin : ", users)
fmt.Println("ret : ", res)
}

0 comments on commit 84ac45b

Please sign in to comment.