Skip to content

Commit

Permalink
Add GroupBy (#189)
Browse files Browse the repository at this point in the history
GroupBy groups slice elements by key returned by getKey function for each
slice element.

It returns a map in which slices of elements of original slice are matched
to keys defined by getKey function. It returns non-nil map, if empty or nil
slice is passed.

For example, if you want to group integers by their remainder from division
by 5, you can use this function as follows:

	_ = pie.GroupBy(
	    []int{23, 76, 37, 11, 23, 47},
	    func(num int) int {
	        return num % 5
	    },
	)

In above case map {1:[76, 11], 2:[37, 47], 3:[23, 23]} is returned.

Fixes #188
  • Loading branch information
electrofocus authored Feb 27, 2023
1 parent 4abd3ae commit 42749e4
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
30 changes: 30 additions & 0 deletions v2/groupby.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package pie

// GroupBy groups slice elements by key returned by getKey function for each
// slice element.
//
// It returns a map in which slices of elements of original slice are matched
// to keys defined by getKey function. It returns non-nil map, if empty or nil
// slice is passed.
//
// For example, if you want to group integers by their remainder from division
// by 5, you can use this function as follows:
//
// _ = pie.GroupBy(
// []int{23, 76, 37, 11, 23, 47},
// func(num int) int {
// return num % 5
// },
// )
//
// In above case map {1:[76, 11], 2:[37, 47], 3:[23, 23]} is returned.
func GroupBy[T comparable, U any](values []U, getKey func(U) T) map[T][]U {
groups := make(map[T][]U)

for _, val := range values {
key := getKey(val)
groups[key] = append(groups[key], val)
}

return groups
}
57 changes: 57 additions & 0 deletions v2/groupby_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package pie_test

import (
"testing"

"github.com/elliotchance/pie/v2"
"github.com/stretchr/testify/assert"
)

func TestGroupBy(t *testing.T) {
type Room int

const (
Kitchen Room = iota + 1
Bedroom
Lounge
)

type Item struct {
room Room
name string
}

var (
bed = Item{room: Bedroom, name: "bed"}
table = Item{room: Kitchen, name: "table"}
toaster = Item{room: Kitchen, name: "toaster"}
pillow = Item{room: Bedroom, name: "pillow"}
sofa = Item{room: Lounge, name: "sofa"}
)

groups := pie.GroupBy(
[]Item{
bed,
table,
toaster,
pillow,
sofa,
},
func(item Item) Room {
return item.room
},
)

assert.Equal(
t,
map[Room][]Item{
Kitchen: {table, toaster},
Bedroom: {bed, pillow},
Lounge: {sofa},
},
groups,
)

groups = pie.GroupBy(nil, func(item Item) Room { return item.room })
assert.Equal(t, map[Room][]Item{}, groups)
}

0 comments on commit 42749e4

Please sign in to comment.