Up to Exercise 1-4
[goproglang.git] / dup2.go
1 // Dup2 prints the count and text of lines that appear more than once
2 //in the input. It reads from stdin or from a list of named files.
3 package main
4
5 import (
6         "bufio"
7         "fmt"
8         "os"
9 )
10
11 type val struct {
12         amount int
13         files  []string
14 }
15
16 func main() {
17         counts := make(map[string]val)
18         files := os.Args[1:]
19         if len(files) == 0 {
20                 countLines(os.Stdin, counts)
21         } else {
22                 for _, arg := range files {
23                         f, err := os.Open(arg)
24                         if err != nil {
25                                 fmt.Fprintf(os.Stderr, "dup2: %v\n", err)
26                         }
27                         countLines(f, counts)
28                         f.Close()
29                 }
30         }
31         for line, v := range counts {
32                 if v.amount > 1 {
33                         fs := unique(v.files)
34                         fmt.Printf("%d\t%s\t%s\n", v.amount, line, fs)
35                 }
36         }
37 }
38
39 func unique(strSlice []string) []string {
40         keys := make(map[string]bool)
41         list := []string{}
42         for _, entry := range strSlice {
43                 if _, value := keys[entry]; !value {
44                         keys[entry] = true
45                         list = append(list, entry)
46                 }
47         }
48         return list
49 }
50
51 func countLines(f *os.File, counts map[string]val) {
52         input := bufio.NewScanner(f)
53         for input.Scan() {
54                 t := input.Text()
55                 pair := counts[t]
56                 pair.amount++
57                 pair.files = append(pair.files, f.Name())
58                 // fmt.Printf("%s %d %s\n", input.Text(), pair.amount, pair.files)
59                 counts[t] = pair
60         }
61 }