diff --git a/join.go b/join.go index 1b2b60b..c681015 100644 --- a/join.go +++ b/join.go @@ -1,7 +1,7 @@ package underscore // Joins two slices together and returns a Tuple of [T, []P], the selectors allow you to pick the -// keys from your structure you would like to join the sets together with +// keys you want to use from your struct's to join the sets together func Join[T, P any, S comparable]( left []T, right []P, @@ -18,18 +18,17 @@ func Join[T, P any, S comparable]( return results } -// Joins two slices together and returns a []R where R is defined by the output of your projection -// function -// The selectors allow you to pick the keys from your structure you would like to join the sets -// together with. -// While the projection functions allows you to reformat joined datasets contains in the -// Tuple of [T, []P] into your own structure or type -func JoinProject[T, P, R any, S comparable]( - left []T, - right []P, - leftSelector func(T) S, - rightSelector func(P) S, - projection func(Tuple[T, []P]) R) (results []R) { +// Joins two slices together and returns a []O where O is defined by the output +// of your projection function +// The selectors allow you to pick the keys from your structure to use as the join keys +// While the projection functions allows you to reformat joined datasets +// (Tuple of [T, []P]) into your own struct or type +func JoinProject[L, R, O any, S comparable]( + left []L, + right []R, + leftSelector func(L) S, + rightSelector func(R) S, + projection func(Tuple[L, []R]) O) (results []O) { for _, x := range Join(left, right, leftSelector, rightSelector) { results = append(results, projection(x)) diff --git a/join_test.go b/join_test.go index fbf0d4d..1159af5 100644 --- a/join_test.go +++ b/join_test.go @@ -1,30 +1,45 @@ package underscore_test import ( - "reflect" "testing" u "github.com/rjNemo/underscore" + "github.com/stretchr/testify/assert" ) -func Test_Join_Can_Join_Two_Slices_Together(t *testing.T) { - one := u.Tuple[int, string]{Left: 1, Right: "One"} - two := u.Tuple[int, string]{Left: 2, Right: "Two"} - three := u.Tuple[int, string]{Left: 3, Right: "Three"} +var zero = u.Tuple[int, string]{Left: 0, Right: "Zero"} +var one = u.Tuple[int, string]{Left: 1, Right: "One"} +var two = u.Tuple[int, string]{Left: 2, Right: "Two"} +var three = u.Tuple[int, string]{Left: 3, Right: "Three"} - var left = []u.Tuple[int, string]{one, two, three} +func Test_Join_Can_Join_Two_Slices_Together(t *testing.T) { + var left = []u.Tuple[int, string]{zero, one, two, three} var right = []u.Tuple[int, string]{one, three, two, three, two, three} selector := func(x u.Tuple[int, string]) int { return x.Left } var joined = u.Join(left, right, selector, selector) var want = []u.Tuple[u.Tuple[int, string], []u.Tuple[int, string]]{ + {Left: zero, Right: nil}, {Left: one, Right: []u.Tuple[int, string]{one}}, {Left: two, Right: []u.Tuple[int, string]{two, two}}, {Left: three, Right: []u.Tuple[int, string]{three, three, three}}, } - if !reflect.DeepEqual(joined, want) { - t.Errorf("Expected to get %v but we got %v instead", want, joined) - } + assert.Equal(t, want, joined) +} + +func Test_Join_Can_Join_and_Project_Two_Slices_Together(t *testing.T) { + var left = []u.Tuple[int, string]{zero, one, two, three} + var right = []u.Tuple[int, string]{one, three, two, three, two, three} + + selector := func(x u.Tuple[int, string]) int { return x.Left } + project := func(x u.Tuple[u.Tuple[int, string], []u.Tuple[int, string]]) int { + return len(x.Right) // projecting to a could of how many + } + + var joined = u.JoinProject(left, right, selector, selector, project) + var want = []int{0, 1, 2, 3} + + assert.Equal(t, want, joined) } diff --git a/orderBy.go b/orderBy.go index 36435c5..8ee7671 100644 --- a/orderBy.go +++ b/orderBy.go @@ -1,12 +1,13 @@ package underscore -// Orders a slice by a field value within a struct, the predicate allow you +// Orders a slice by a field value within a struct, the predicate allows you // to pick the fields you want to orderBy. Use > for ASC or < for DESC -// func (left Person, right Person) bool { return person.Age > person.Age } +// func (left Person, right Person) bool { return left.Age > right.Age } func OrderBy[T any](list []T, predicate func(T, T) bool) []T { swaps := true var tmp T + //todo: replace with a faster algorithm, this one is pretty simple for swaps { swaps = false