【问题标题】:Golang grouping files of same extensionGolang 对相同扩展名的文件进行分组
【发布时间】:2021-02-14 10:41:01
【问题描述】:

我正在用 Golang 编写一个基本程序,它输出当前目录中的文件数以及每个文件包含多少行代码:

我现在正在尝试对具有相同扩展名的文件进行分组,但遇到了问题。 所以,我所做的是将字符串映射声明为键,将字符串切片声明为值:

将 extname 存储为密钥,并将其文件存储在该切片中

var m = make(map[string][]string)

我首先在“组”函数中收到程序读取的文件片段(q 参数),如下所示:

[.gitignore README.md cmd\root.go example.go eyeball.exe go.mod go.sum main.go utils\utils.go]

然后我对该片文件进行操作:



func group(q []string) {

    var ext string
    var checkedext []string

    for _, val := range q {
        ext = strings.Split(val, ".")[1]
        for _, foo := range q {
            secext := strings.Split(foo, ".")[1]
            if ext == secext {
                if !contains(checkedext, ext) {
                    addtogroup(ext, foo)
                    checkedext = append(checkedext, ext)
                }
            }
        }
    }
    fmt.Println(m)

}

func contains(s []string, item string) bool {
    for _, el := range s {
        if el == item {
            return true
        }
    }
    return false
}

var m = make(map[string][]string)


func addtogroup(ext, file string) {

    var subgroup []string
    if val, ok := m[ext]; ok {
       val = append(val, file)
    } else {
        subgroup = append(subgroup, file)
        m[ext] = subgroup
    }
}

当我打印地图时,它会输出:

map[exe:[eyeball.exe] gitignore:[.gitignore] go:[cmd\root.go] md:[README.md] mod:[go.mod] sum:[go.sum]]

但是,上面的输出是错误的,因为我有 3 个 .go 文件。

我知道范围会遍历地图的副本,我无法通过指针引用它,因为地图本身就是一个引用,我找不到解决方法, 我想做这个:

var m = make(map[string]*Data)

但我不知道这是否是最好的做法

我努力解释我想让我的程序做什么以及它做了什么,如果我遗漏了任何细节,请指出我。

【问题讨论】:

    标签: dictionary go slice


    【解决方案1】:

    问题在于,当您将元素添加到切片(位于地图内)时,您必须重新分配结果切片,因为append() 返回一个包含附加项的新切片标头:

    if val, ok := m[ext]; ok {
       val = append(val, file)
        m[ext] = val
    } else {
        // ...
    }
    

    或者简单地说:

    m[ext] = append(m[ext], file)
    

    如果ext 尚未在映射中,这也会处理,因为m[ext] 将是值类型的零值(即[]string),而零值是nil 切片。您可以附加到nil 切片。

    还要获取扩展名,请使用filepath.Ext()

    您的group() 函数可以这么简单:

    func group(names []string) map[string][]string {
        m := map[string][]string{}
        for _, name := range names {
            ext := filepath.Ext(name)
            ext = strings.TrimPrefix(ext, ".")
            m[ext] = append(m[ext], name)
        }
        return m
    }
    

    测试它:

    fmt.Println(group([]string{"x\\a.txt", "b.txt", "c.go"}))
    
    fmt.Println(group([]string{"a.go", "xy\\b.go", "c.txt"}))
    

    哪些输出(在Go Playground 上试试):

    map[go:[c.go] txt:[x\a.txt b.txt]]
    map[go:[a.go xy\b.go] txt:[c.txt]]
    

    查看相关问题:

    How to update map values in Go

    How to categorize list of objects based on a parameter

    【讨论】:

    • 看看我写了多少行代码来完成这个基本功能和你的解决方案:)
    • 我可以使用我之前在问题中显示的结构(数据)吗?如果可以,你能告诉我怎么做吗?以及是否会是更好的方法?
    • @MohamedTarek 你没有展示你是如何想象的,但切片是一个包含指向支持数组的指针的小结构,所以它类似于使用*Data。我认为我提出的解决方案非常清晰、紧凑且高效。我不知道您还想用Data 做什么。
    猜你喜欢
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多