funk.GroupBY
arshpreetsingh opened this issue · comments
Arshpreet Singh commented
Is there any way I can use funck.Groupby?
Flo commented
There is no funk.GroupBy
, you can implement it if you want and send me a PR.
Johan Kjölhede commented
I dont know if it is possible to re-open, or if you could make use of this directly.
groupBy is absolutely essential imo for this very fine library :D
Here is an idea of how it could be implemented (BIG WARNING: I started learning go 2 days ago so I am probably breaking every convention in the book!)
func GroupBy(list interface{}, pivotFunc interface{}) interface{} {
if !funk.IsCollection(list) {
panic(fmt.Sprintf("%v must be a collection (slice or array)", list))
}
// cheating here by using funk.Map, to get funk validation :).
// Could have used reflect to call the pivot function, but then
// I would need to re-implement all nice checks in go-funk
keys := funk.Map(list, pivotFunc)
count := reflect.ValueOf(keys).Len()
keysR := reflect.ValueOf(keys)
valuesR := reflect.ValueOf(list)
valueType := valuesR.Type().Elem()
keyType := reflect.TypeOf(pivotFunc).Out(0)
sliceType := reflect.SliceOf(valueType)
resultType := reflect.MapOf(keyType, sliceType)
resultR := reflect.MakeMapWithSize(resultType, 0)
initGroupCap := 1 + count/3
if initGroupCap > 10 {
initGroupCap = 10
}
for i := 0; i < count; i++ {
keyR := keysR.Index(i)
valueR := valuesR.Index(i)
groupR := resultR.MapIndex(keyR)
if groupR == (reflect.Value{}) {
groupR = reflect.MakeSlice(sliceType, 0, initGroupCap)
}
newGroup := reflect.Append(groupR, valueR)
resultR.SetMapIndex(keyR, newGroup)
}
return resultR.Interface()
}
}
With this, I can do the following
k8sResources := ... // []*kubectl.K8sResource
k8sResourcesByNamespace := coll.GroupBy(k8sResources, func(r *kubectl.K8sResource) string {
return r.MetaData.Namespace
}).(map[string][]*kubectl.K8sResource)
for namespace, resources := range k8sResourcesByNamespace {
....
for _, resource := range resources {
...
Johan Kjölhede commented
solved by #141