package redhat import ( "bufio" "fmt" "os" "sort" "strings" ) // HandleLine the custom func type for processing a line and push data into the map type HandleLine func(contentMap map[string]int, line string) // AnalyseData analyse data with sort, uniq and sort by count func (fa *FileAnalyser) AnalyseData() error { contentMap, err := fa.parseContent(fa.file, processLineWithWhiteSpace) if err != nil { return err } fa.transformFromMapToDataRows(contentMap) fa.sortDataRows() return nil } func (fa *FileAnalyser) parseContent(file *os.File, handler HandleLine) (map[string]int, error) { contentMap := make(map[string]int) scanner := bufio.NewScanner(file) defer file.Close() for scanner.Scan() { handler(contentMap, scanner.Text()) } if err := scanner.Err(); err != nil { return nil, fmt.Errorf("fail to read and process content: %s", err.Error()) } return contentMap, nil } func (fa *FileAnalyser) sortDataRows() { sort.SliceStable(fa.dataRows, func(i, j int) bool { if firstItemHasMoreCount(fa, i, j) { return true } return compareRowsWhenAreSameCount(fa, i, j) }) } func (fa *FileAnalyser) transformFromMapToDataRows(contentMap map[string]int) { for key, value := range contentMap { fa.dataRows = append(fa.dataRows, dataRow{ word: key, count: value, }) } } func processLineWithWhiteSpace(contentMap map[string]int, line string) { words := strings.Fields(line) for _, word := range words { count, ok := contentMap[word] if !ok { contentMap[word] = 1 continue } contentMap[word] = count + 1 } } func firstItemHasMoreCount(fa *FileAnalyser, i int, j int) bool { return fa.dataRows[i].count > fa.dataRows[j].count } func compareRowsWhenAreSameCount(fa *FileAnalyser, i int, j int) bool { return (fa.dataRows[i].count == fa.dataRows[j].count) && fa.dataRows[i].word > fa.dataRows[j].word }