the question is simple, for a input [apple, banana, orange, apple, banana, apple], the program will count it as a map: {apple : 3, orange: 1, banana: 2}, then sort this map by it's values, get [(apple, 3), (banana, 2), (orange, 1)] below is my go version, I'm a go newbie, could you please review it and lecture me how to polish the code? I add a python version for reference
package main
//input, a url.log file, like "apple\nbanana\norange\napple\nbanana\napple\n"
//output, a output.txt file, should be "apple: 3\nbanana: 2\norange: 1\n"
import (
"fmt"
"bufio"
"os"
"sort"
"strings"
"io"
)
func main() {
m := make(map[string]int)
// read file line by line
filename := "url.log"
f, err := os.Open(filename)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
r := bufio.NewReader(f)
for line, err := r.ReadString('\n'); err == nil; {
url := strings.TrimRight(line, "\n")
m[url] += 1 // build the map
line, err = r.ReadString('\n')
}
if err != nil {
fmt.Println(err)
return
}
//sort the map by it's value
vs := NewValSorter(m)
vs.Sort()
// output
f_out, _ := os.Create("output.go.txt")
defer f_out.Close()
var line string
for i, k := range vs.Keys {
line = fmt.Sprintf("%s: %d\n", k, vs.Vals[i])
io.WriteString(f_out, line)
}
}
type ValSorter struct {
Keys []string
Vals []int
}
func NewValSorter(m map[string]int) *ValSorter {
vs := &ValSorter {
Keys: make([]string, 0, len(m)),
Vals: make([]int, 0, len(m)),
}
for k, v := range m {
vs.Keys = append(vs.Keys, k)
vs.Vals = append(vs.Vals, v)
}
return vs
}
func (vs *ValSorter) Sort() {
sort.Sort(vs)
}
func (vs *ValSorter) Len() int {
return len(vs.Vals)
}
func (vs *ValSorter) Less(i, j int) bool {
return vs.Vals[i] > vs.Vals[j]
}
func (vs *ValSorter) Swap(i, j int) {
vs.Vals[i], vs.Vals[j] = vs.Vals[j], vs.Vals[i]
vs.Keys[i], vs.Keys[j] = vs.Keys[j], vs.Keys[i]
}
python version:
from collections import Counter
def main():
count = Counter()
with open("url.log", "rb") as f:
for line in f:
url = line.rstrip()
count[url] += 1
with open("output.py.txt", "wb") as f:
for key, value in count.most_common():
f.write("%s: %d\n" %(key, value))
if __name__ == "__main__":
main()