github.com/seeker-insurance/kit@v0.0.13/pretty/text/cmd/agg/main.go (about)

     1  package main
     2  
     3  // TODO(kr): tests
     4  
     5  import (
     6  	"bufio"
     7  	"fmt"
     8  	"log"
     9  	"math/rand"
    10  	"os"
    11  	"strings"
    12  	"time"
    13  )
    14  
    15  type agg interface {
    16  	merge(string)
    17  	String() string
    18  }
    19  
    20  var (
    21  	key     = 0
    22  	funcmap = make(map[int]func(init, arg string) agg)
    23  	argmap  = make(map[int]string)
    24  	symtab  = map[string]func(init, arg string) agg{
    25  		"first":  first,
    26  		"last":   last,
    27  		"prefix": prefix,
    28  		"sample": sample,
    29  		"join":   join,
    30  		"smin":   smin,
    31  		"smax":   smax,
    32  		"min":    min,
    33  		"max":    max,
    34  		"sum":    sum,
    35  		"mean":   mean,
    36  		"count":  count,
    37  		"const":  constf,
    38  		"drop":   nil,
    39  	}
    40  )
    41  
    42  func main() {
    43  	log.SetPrefix("agg: ")
    44  	log.SetFlags(0)
    45  	rand.Seed(time.Now().UnixNano())
    46  	for i, sym := range os.Args[1:] {
    47  		if p := strings.IndexByte(sym, ':'); p >= 0 {
    48  			sym, argmap[i] = sym[:p], sym[p+1:]
    49  		}
    50  		if sym == "key" {
    51  			key, sym = i, "first"
    52  		}
    53  		f, ok := symtab[sym]
    54  		if !ok {
    55  			log.Fatalf("bad function: %q", sym)
    56  		}
    57  		funcmap[i] = f
    58  	}
    59  
    60  	sc := bufio.NewScanner(os.Stdin)
    61  	var g *group
    62  	for sc.Scan() {
    63  		ss := strings.Fields(sc.Text())
    64  		if !matches(g, ss) {
    65  			emit(g)
    66  			g = &group{key: ss[key]}
    67  		}
    68  		mergeLine(g, ss)
    69  	}
    70  	emit(g)
    71  }
    72  
    73  type group struct {
    74  	key string
    75  	agg []agg
    76  }
    77  
    78  func matches(g *group, ss []string) bool {
    79  	return g != nil && g.key == ss[key]
    80  }
    81  
    82  func emit(g *group) {
    83  	if g == nil {
    84  		return
    85  	}
    86  	rest := false
    87  	for i, a := range g.agg {
    88  		if f, ok := funcmap[i]; ok && f == nil {
    89  			continue
    90  		}
    91  		if rest {
    92  			fmt.Print("\t")
    93  		}
    94  		rest = true
    95  		fmt.Print(a)
    96  	}
    97  	fmt.Println()
    98  }
    99  
   100  func mergeLine(g *group, ss []string) {
   101  	for i, s := range ss {
   102  		if i >= len(g.agg) {
   103  			f := funcmap[i]
   104  			if f == nil {
   105  				f = first
   106  			}
   107  			g.agg = append(g.agg, f(s, argmap[i]))
   108  		} else {
   109  			g.agg[i].merge(s)
   110  		}
   111  	}
   112  }