snippetpythonMinor
code review for count then sort problems (go lang)
Viewed 0 times
sortforthencodecountproblemsreviewlang
Problem
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) {
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) {
Solution
In Go, I would write:
Input (
Output (
package main
import (
"bufio"
"fmt"
"io"
"os"
"sort"
)
type Key string
type Count int
type Elem struct {
Key
Count
}
type Elems []*Elem
func (s Elems) Len() int {
return len(s)
}
func (s Elems) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
type ByReverseCount struct{ Elems }
func (s ByReverseCount) Less(i, j int) bool {
return s.Elems[j].Count < s.Elems[i].Count
}
func main() {
m := make(map[Key]Count)
fi, err := os.Open("keys.txt")
if err != nil {
fmt.Println(err)
return
}
defer fi.Close()
r := bufio.NewReader(fi)
for {
line, err := r.ReadString('\n')
if err != nil {
if err == io.EOF && len(line) == 0 {
break
}
fmt.Println(err)
return
}
key := line[:len(line)-1]
m[Key(key)] += 1
}
fi.Close()
e := make(Elems, 0, len(m))
for k, c := range m {
e = append(e, &Elem{k, c})
}
sort.Sort(ByReverseCount{e})
fo, err := os.Create("counts.txt")
if err != nil {
fmt.Println(err)
return
}
defer fo.Close()
for _, e := range e {
line := fmt.Sprintf("%s: %d\n", e.Key, e.Count)
fo.WriteString(line)
}
}Input (
keys.txt):apple
banana
orange
apple
banana
appleOutput (
counts.txt):apple: 3
banana: 2
orange: 1Code Snippets
package main
import (
"bufio"
"fmt"
"io"
"os"
"sort"
)
type Key string
type Count int
type Elem struct {
Key
Count
}
type Elems []*Elem
func (s Elems) Len() int {
return len(s)
}
func (s Elems) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
type ByReverseCount struct{ Elems }
func (s ByReverseCount) Less(i, j int) bool {
return s.Elems[j].Count < s.Elems[i].Count
}
func main() {
m := make(map[Key]Count)
fi, err := os.Open("keys.txt")
if err != nil {
fmt.Println(err)
return
}
defer fi.Close()
r := bufio.NewReader(fi)
for {
line, err := r.ReadString('\n')
if err != nil {
if err == io.EOF && len(line) == 0 {
break
}
fmt.Println(err)
return
}
key := line[:len(line)-1]
m[Key(key)] += 1
}
fi.Close()
e := make(Elems, 0, len(m))
for k, c := range m {
e = append(e, &Elem{k, c})
}
sort.Sort(ByReverseCount{e})
fo, err := os.Create("counts.txt")
if err != nil {
fmt.Println(err)
return
}
defer fo.Close()
for _, e := range e {
line := fmt.Sprintf("%s: %d\n", e.Key, e.Count)
fo.WriteString(line)
}
}apple
banana
orange
apple
banana
appleapple: 3
banana: 2
orange: 1Context
StackExchange Code Review Q#9146, answer score: 4
Revisions (0)
No revisions yet.