106 lines
2.0 KiB
Go
106 lines
2.0 KiB
Go
package iter
|
|
|
|
type groupBy struct {
|
|
curKey interface{}
|
|
curKeyOk bool
|
|
curValue interface{}
|
|
keyFunc func(interface{}) interface{}
|
|
input Iterator
|
|
groupKey interface{}
|
|
groupKeyOk bool
|
|
}
|
|
|
|
type Group interface {
|
|
Iterator
|
|
Key() interface{}
|
|
}
|
|
|
|
type group struct {
|
|
gb *groupBy
|
|
key interface{}
|
|
first bool
|
|
stopped bool
|
|
}
|
|
|
|
func (me *group) Stop() {
|
|
me.stopped = true
|
|
}
|
|
|
|
func (me *group) Next() (ok bool) {
|
|
if me.stopped {
|
|
return false
|
|
}
|
|
if me.first {
|
|
me.first = false
|
|
return true
|
|
}
|
|
me.gb.advance()
|
|
if !me.gb.curKeyOk || me.gb.curKey != me.key {
|
|
me.Stop()
|
|
return
|
|
}
|
|
ok = true
|
|
return
|
|
}
|
|
|
|
func (me group) Value() (ret interface{}) {
|
|
if me.stopped {
|
|
panic("iterator stopped")
|
|
}
|
|
ret = me.gb.curValue
|
|
return
|
|
}
|
|
|
|
func (me group) Key() interface{} {
|
|
return me.key
|
|
}
|
|
|
|
func (me *groupBy) advance() {
|
|
me.curKeyOk = me.input.Next()
|
|
if me.curKeyOk {
|
|
me.curValue = me.input.Value()
|
|
me.curKey = me.keyFunc(me.curValue)
|
|
}
|
|
}
|
|
|
|
func (me *groupBy) Next() (ok bool) {
|
|
for me.curKey == me.groupKey {
|
|
ok = me.input.Next()
|
|
if !ok {
|
|
return
|
|
}
|
|
me.curValue = me.input.Value()
|
|
me.curKey = me.keyFunc(me.curValue)
|
|
me.curKeyOk = true
|
|
}
|
|
me.groupKey = me.curKey
|
|
me.groupKeyOk = true
|
|
return true
|
|
}
|
|
|
|
func (me *groupBy) Value() (ret interface{}) {
|
|
return &group{me, me.groupKey, true, false}
|
|
}
|
|
|
|
func (me *groupBy) Stop() {
|
|
}
|
|
|
|
// Allows use of nil as a return from the key func.
|
|
var uniqueKey = new(int)
|
|
|
|
// Group by returns an iterator of iterators over the values of the input
|
|
// iterator that consecutively return the same value when input to the key
|
|
// function. Note that repeated calls to each value of the GroupBy Iterator
|
|
// does not return a new iterator over the values for that key.
|
|
func GroupBy(input Iterator, keyFunc func(interface{}) interface{}) Iterator {
|
|
if keyFunc == nil {
|
|
keyFunc = func(a interface{}) interface{} { return a }
|
|
}
|
|
return &groupBy{
|
|
input: input,
|
|
keyFunc: keyFunc,
|
|
groupKey: uniqueKey,
|
|
curKey: uniqueKey,
|
|
}
|
|
}
|