Go 练习01.统计文本行出现频次/查找重复的行

从标准输入读取文本,统计相同文本出现的次数

package main
import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    // 统计文本 {"文本1":5 }  即`文本1`出现5次
    counts := make(map[string]int)
    
    // os.Stdin 是标准输入, 就是屏幕终端输入的信息
    // bufio.NewScanner 创建并返回从 `标准输入中` 读取数据的Scanner
    // Scanner 类型是什么呢?提供了方便的读取数据的接口,如从换行符分隔的文本里读取每一行 
    input := bufio.NewScanner(os.Stdin)
    
    // 调用Scanner.Scan()返回的是true/false
    // 他判断的是 是否有输入, ctrl+D 则返回false,他是阻塞的
    // 当它执行后,调用input.Text() 就可以获取到值,
    // 如果连续执行两次Scanner.Scan(),则第一次的值就会被跳过
    // 文档中有个token的概念,它就是让Scanner的扫描位置移动到下一个token,
    // 如果你不使用Bytes或Text方法获得值,则会错过。
    for input.Scan() {
        // 不用担心没有 ,我们设置的int类型 ,默认没有初始值为0
        counts[input.Text()]++
    }

    // ctrl+D 后上面的for循环会终止(不满足循环条件)
    
    // 遍历map key:value
    for line, n := range counts {
        if n >= 1 {
            fmt.Print(line,,n)
        }
    }
}

go run find.go 没有参数,则从标准输入中读取数据

go run find.go 1.txt 2.txt ... 有参数,则从对应的文件中读取数据

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    counts := make(map[string]int)
    
    files := os.Args[1:]
    
    if len(files) == 0 {
        countLines(os.Stdin, counts)
    } else {
        for _, arg := range files {
            // os.Open打开文件
            f, err := os.Open(arg)
            if err != nil {
                // 标准错误输出
                fmt.Fprintf(os.Stderr, "dup2: %v\n", err)
                continue
            }
            countLines(f, counts)
            f.Close()
        }
    }
    
    for line, n := range counts {
        if n >= 1 {
            fmt.Printf("%d\t%s\n", n, line)
        }
    }
}

func countLines(f *os.File, counts map[string]int) {
    input := bufio.NewScanner(f)
    for input.Scan() {
        counts[input.Text()]++
    }
}

只读文件 不读标准输入,换一个方法读取文件 io/ioutil

package main

import (
    "fmt"
    "io/ioutil"
    "os"
    "strings"
)

func main() {
    
    counts := make(map[string]int)
    
    for _, filename := range os.Args[1:] {
        // data 是 字节切片(byte slice)
        data, err := ioutil.ReadFile(filename)
        if err != nil {
            fmt.Fprintf(os.Stderr, "dup3: %v\n", err)
            continue
        }
        // 把切片转成string, 使用Split分割,
        // 这里最后一个元素为"" 因为最后一个是换行符,所以比预期的多一个""
        for _, line := range strings.Split(string(data), "\n") {
            counts[line]++
        }
    }
    
    for line, n := range counts {
        if n >= 1 {
            fmt.Printf("%d\t%s\n", n, line)
        }
    }
}

补充printf

%d          十进制整数
%x, %o, %b  十六进制,八进制,二进制整数。
%f, %g, %e  浮点数: 3.141593 3.141592653589793 3.141593e+00
%t          布尔:true或false
%c          字符(rune) (Unicode码点)
%s          字符串
%q          带双引号的字符串"abc"或带单引号的字符'c'
%v          变量的自然形式(natural format)
%T          变量的类型
%%          字面上的百分号标志(无操作数)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值