使用 Golang 对文件名中带有数字的字符串进行排序

Loc*_*ust 5 sorting string numbers go

我正在尝试将一些旧的 python 代码转换为 Go lang。但是我在对文件夹中的文件进行排序时遇到了困难。由于文件始终AMA1.txtAMA2.txt等等。在Python源代码我这样做:

files=[]
for file in os.listdir(someDir):

    if file.endswith(".txt"):
     files.append(file) 

convert = lambda text: int(text) if text.isdigit() else text 
alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)',key) ]

files.sort( key=alphanum_key )

for i in files:
    print (i)
Run Code Online (Sandbox Code Playgroud)

我到目前为止,但缺少排序:

func main() {
    dirname := "someDir"
    d, err := os.Open(dirname)

    if err != nil {
        fmt.Println(err)
    }

    defer d.Close()

    fi, err := d.Readdir(-1)

    if err != nil {
        fmt.Println(err)
    }

    for _, fi := range fi {
        if fi.Mode().IsRegular() {
            fmt.Println(fi.Name())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

pet*_*rSO 5

Go 有一个sort。从带有非负整数后缀的名称构造可排序的名称。

例如,

package main

import (
    "encoding/binary"
    "fmt"
    "os"
    "path/filepath"
    "sort"
    "strconv"
)

// sortName returns a filename sort key with
// non-negative integer suffixes in numeric order.
// For example, amt, amt0, amt2, amt10, amt099, amt100, ...
func sortName(filename string) string {
    ext := filepath.Ext(filename)
    name := filename[:len(filename)-len(ext)]
    // split numeric suffix
    i := len(name) - 1
    for ; i >= 0; i-- {
        if '0' > name[i] || name[i] > '9' {
            break
        }
    }
    i++
    // string numeric suffix to uint64 bytes
    // empty string is zero, so integers are plus one
    b64 := make([]byte, 64/8)
    s64 := name[i:]
    if len(s64) > 0 {
        u64, err := strconv.ParseUint(s64, 10, 64)
        if err == nil {
            binary.BigEndian.PutUint64(b64, u64+1)
        }
    }
    // prefix + numeric-suffix + ext
    return name[:i] + string(b64) + ext
}

func main() {
    dirname := "someDir"
    d, err := os.Open(dirname)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer d.Close()
    fi, err := d.Readdir(-1)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println("\nUnsorted:")
    for _, fi := range fi {
        if fi.Mode().IsRegular() {
            fmt.Println(fi.Name())
        }
    }

    sort.Slice(
        fi,
        func(i, j int) bool {
            return sortName(fi[i].Name()) < sortName(fi[j].Name())
        },
    )

    fmt.Println("\nSorted:")
    for _, fi := range fi {
        if fi.Mode().IsRegular() {
            fmt.Println(fi.Name())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Unsorted:
amt099.txt
amt.txt
amt2.txt
amt100.txt
amt10.txt
amt1.txt

Sorted:
amt.txt
amt1.txt
amt2.txt
amt10.txt
amt099.txt
amt100.txt
Run Code Online (Sandbox Code Playgroud)


jre*_*ior -1

将每个项目收集到一个切片中,然后使用sort对它们进行排序。包文档中有示例和解释。

对于您的情况,在排序之前提取数字可能会更容易。为此,您可能会发现fmt.Sscanf有用。