HiveBrain v1.2.0
Get Started
← Back to all entries
snippetpythonMinor

code review for count then sort problems (go lang)

Submitted by: @import:stackexchange-codereview··
0
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) {

Solution

In Go, I would write:

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
apple


Output (counts.txt):

apple: 3
banana: 2
orange: 1

Code 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
apple
apple: 3
banana: 2
orange: 1

Context

StackExchange Code Review Q#9146, answer score: 4

Revisions (0)

No revisions yet.