From 86a61da36fdf322720c6d22fc8c7a208c81bff8d Mon Sep 17 00:00:00 2001 From: Jan Novak Date: Wed, 2 Sep 2026 09:34:03 +0200 Subject: [PATCH] 04-log-topn: implement TopN with bufio.Scanner and slices.SortFunc Count paths in a map, copy into []KV, sort by count descending with cmp.Compare, truncate to n. Scanner buffer raised to 1MB for long lines; malformed lines (<3 fields) are skipped. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_012MpK9niZm4jcs3mAJbxMfi --- 04-log-topn/main.go | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/04-log-topn/main.go b/04-log-topn/main.go index 03d8dc6..93e6fe3 100644 --- a/04-log-topn/main.go +++ b/04-log-topn/main.go @@ -4,7 +4,7 @@ // ---------- // Log lines look like: // -// 2026-08-28T10:00:01Z GET /api/users 200 123ms +// 2026-08-28T10:00:01Z GET /api/users 200 123ms // // Implement TopN(r, n) so that it: // @@ -20,8 +20,11 @@ package main import ( + "bufio" + "cmp" "fmt" "io" + "slices" "strings" ) @@ -38,7 +41,38 @@ func TopN(r io.Reader, n int) ([]KV, error) { // - map[string]int for counting // - copy map into []KV and sort by count desc (maps can't be sorted) // - truncate to n - return nil, nil + + m := make(map[string]int) + sc := bufio.NewScanner(r) + sc.Buffer(make([]byte, 0, 64*1024), 1024*1024) + for sc.Scan() { + //fmt.Println(sc.Text()) + fields := strings.Fields(sc.Text()) + //fmt.Printf("len: %v, fields: %v\n", len(fields), fields) + if len(fields) < 3 { + continue + } + m[fields[2]]++ + } + + // copy over map into list of KV + l := make([]KV, len(m)) + i := 0 + for k, v := range m { + // println(i, k, v, len(l), len(m)) + l[i] = KV{k, v} + i++ + } + + // sort by count desc + slices.SortFunc(l, func(a, b KV) int { + return cmp.Compare(b.Count, a.Count) + }) + if len(l) > n { + l = l[:n] + } + + return l, nil } func main() {