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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MpK9niZm4jcs3mAJbxMfi
This commit is contained in:
+36
-2
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user