1
0
mirror of https://github.com/MontFerret/ferret.git synced 2024-12-14 11:23:02 +02:00
ferret/pkg/runtime/collections/group.go
2018-09-18 16:42:38 -04:00

86 lines
1.5 KiB
Go

package collections
import (
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
)
type (
GroupKey func(value core.Value) (core.Value, error)
GroupIterator struct {
src Iterator
keys []GroupKey
ready bool
values *MapIterator
}
)
func NewGroupIterator(
src Iterator,
keys ...GroupKey,
) (*GroupIterator, error) {
if core.IsNil(src) {
return nil, core.Error(core.ErrMissedArgument, "source")
}
if len(keys) == 0 {
return nil, core.Error(core.ErrMissedArgument, "key(s)")
}
return &GroupIterator{src, keys, false, nil}, nil
}
func (iterator *GroupIterator) HasNext() bool {
if !iterator.ready {
iterator.ready = true
groups, err := iterator.group()
if err != nil {
iterator.values = NewMapIterator(map[string]core.Value{})
return false
}
iterator.values = groups
}
return iterator.values.HasNext()
}
func (iterator *GroupIterator) Next() (core.Value, core.Value, error) {
return iterator.values.Next()
}
func (iterator *GroupIterator) group() (*MapIterator, error) {
groups := make(map[string]core.Value)
for iterator.src.HasNext() {
for _, keyFn := range iterator.keys {
val, _, err := iterator.src.Next()
if err != nil {
return nil, err
}
keyVal, err := keyFn(val)
if err != nil {
return nil, err
}
key := keyVal.String()
group, exists := groups[key]
if !exists {
group = values.NewArray(10)
groups[key] = group
}
group.(*values.Array).Push(val)
}
}
return NewMapIterator(groups), nil
}