76 lines
1.3 KiB
Go
76 lines
1.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
)
|
|
|
|
type (
|
|
inputFn func() ([]result, error)
|
|
outputFn func([]result) error
|
|
filterFn func(result) (include bool)
|
|
groupFn func(result) (key string)
|
|
)
|
|
|
|
type pipeline struct {
|
|
input inputFn
|
|
filter filterFn
|
|
groupKey groupFn
|
|
output outputFn
|
|
}
|
|
|
|
func newPipeline() *pipeline {
|
|
return &pipeline{
|
|
filter: noopFilter,
|
|
groupKey: noopGrouper,
|
|
input: textReader(os.Stdin),
|
|
output: textWriter(os.Stdout),
|
|
}
|
|
}
|
|
|
|
func (p *pipeline) from(fn inputFn) *pipeline { p.input = fn; return p }
|
|
func (p *pipeline) to(fn outputFn) *pipeline { p.output = fn; return p }
|
|
func (p *pipeline) filterBy(fn filterFn) *pipeline { p.filter = fn; return p }
|
|
func (p *pipeline) groupBy(fn groupFn) *pipeline { p.groupKey = fn; return p }
|
|
|
|
func (p *pipeline) start() ([]result, error) {
|
|
res, err := p.input()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var (
|
|
out []result
|
|
gres = make(map[string]int)
|
|
)
|
|
|
|
for _, r := range res {
|
|
if !p.filter(r) {
|
|
continue
|
|
}
|
|
|
|
k := p.groupKey(r)
|
|
|
|
if i, ok := gres[k]; ok {
|
|
out[i] = out[i].add(r)
|
|
continue
|
|
}
|
|
gres[k] = len(out)
|
|
|
|
out = append(out, r)
|
|
}
|
|
|
|
err = p.output(out)
|
|
|
|
return out, err
|
|
}
|
|
|
|
// TODO: remove me
|
|
func measure(name string) func() {
|
|
start := time.Now()
|
|
return func() {
|
|
fmt.Printf("%s took %v\n", name, time.Since(start))
|
|
}
|
|
}
|