Skip to content

Instantly share code, notes, and snippets.

@derino
Last active June 1, 2022 14:37
Show Gist options
  • Save derino/79925879f77b5701925710418fc85356 to your computer and use it in GitHub Desktop.
Save derino/79925879f77b5701925710418fc85356 to your computer and use it in GitHub Desktop.
package linq
import (
"testing"
"github.com/ahmetb/go-linq/v3"
)
func JoinBy(outer linq.Query, inner linq.Query, predicate func(interface{}, interface{}) bool) linq.Query {
var innerCopy []interface{}
inner.ToSlice(&innerCopy)
q := outer.SelectManyBy(func(x interface{}) linq.Query {
return linq.From(innerCopy)
}, func(inneritem interface{}, outeritem interface{}) interface{} {
return linq.KeyValue{Key: outeritem, Value: inneritem}
}).Where(func(x interface{}) bool {
return predicate(x.(linq.KeyValue).Key, x.(linq.KeyValue).Value)
})
return q
}
func GroupJoinBy(outer linq.Query, inner linq.Query, predicate func(interface{}, interface{}) bool, selector func(interface{}, []interface{}) interface{}) linq.Query {
q := JoinBy(outer, inner, predicate).
GroupBy(
func(x interface{}) interface{} { return x.(linq.KeyValue).Key },
func(x interface{}) interface{} { return x.(linq.KeyValue).Value }).
Select(func(x interface{}) interface{} {
return selector(x.(linq.Group).Key, x.(linq.Group).Group)
})
return q
}
func TestJoinBy(t *testing.T) {
outer := []int{0, 1, 2}
inner := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
want := []interface{}{
linq.KeyValue{Key: 0, Value: 1},
linq.KeyValue{Key: 0, Value: 2},
linq.KeyValue{Key: 0, Value: 3},
linq.KeyValue{Key: 0, Value: 4},
linq.KeyValue{Key: 0, Value: 5},
linq.KeyValue{Key: 0, Value: 6},
linq.KeyValue{Key: 0, Value: 7},
linq.KeyValue{Key: 0, Value: 8},
linq.KeyValue{Key: 0, Value: 9},
linq.KeyValue{Key: 1, Value: 2},
linq.KeyValue{Key: 1, Value: 3},
linq.KeyValue{Key: 1, Value: 4},
linq.KeyValue{Key: 1, Value: 5},
linq.KeyValue{Key: 1, Value: 6},
linq.KeyValue{Key: 1, Value: 7},
linq.KeyValue{Key: 1, Value: 8},
linq.KeyValue{Key: 1, Value: 9},
linq.KeyValue{Key: 2, Value: 3},
linq.KeyValue{Key: 2, Value: 4},
linq.KeyValue{Key: 2, Value: 5},
linq.KeyValue{Key: 2, Value: 6},
linq.KeyValue{Key: 2, Value: 7},
linq.KeyValue{Key: 2, Value: 8},
linq.KeyValue{Key: 2, Value: 9},
}
q := JoinBy(linq.From(outer), linq.From(inner), func(x interface{}, y interface{}) bool { return x.(int) < y.(int) })
if !validateQuery(q, want) {
t.Errorf("From().JoinBy()=%v expected %v", q.Results(), want)
}
}
func TestGroupJoinBy(t *testing.T) {
outer := []int{0, 1, 2}
inner := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
want := []interface{}{
linq.KeyValue{Key: 0, Value: 9},
linq.KeyValue{Key: 1, Value: 8},
linq.KeyValue{Key: 2, Value: 7},
}
q := GroupJoinBy(
linq.From(outer),
linq.From(inner),
func(i interface{}, j interface{}) bool { return i.(int) < j.(int) },
func(outer interface{}, inners []interface{}) interface{} {
return linq.KeyValue{Key: outer, Value: len(inners)}
})
if !validateQuery(q, want) {
t.Errorf("From().GroupJoinBy()=%v expected %v", q.Results(), want)
}
}
// From github.com/ahmetb/go-linq/setup_test.go
func validateQuery(q linq.Query, output []interface{}) bool {
next := q.Iterate()
for _, oitem := range output {
qitem, _ := next()
if oitem != qitem {
return false
}
}
_, ok := next()
_, ok2 := next()
return !(ok || ok2)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment