【问题标题】:How to sort glob.glob numerically?如何对 glob.glob 进行数字排序?
【发布时间】:2020-07-16 18:32:22
【问题描述】:

我有一堆文件在一个文件夹中按数字排序,当我尝试对 glob.glob 进行排序时,我从来没有按正确的顺序得到文件。


文件示例和预期的输出排序

folder
------
C:\Users\user\Desktop\folder\1 sample.mp3
C:\Users\user\Desktop\folder\2 sample.mp3
C:\Users\user\Desktop\folder\3 sample.mp3
C:\Users\user\Desktop\folder\4 sample.mp3
C:\Users\user\Desktop\folder\5 sample.mp3
... over 800 files...

我试过了,但输出似乎是随机的

files = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=lambda x: (os.path.splitext(os.path.basename(x))[0]))


C:\Users\user\Desktop\folder\1 speech.mp3
C:\Users\user\Desktop\folder\10 speech.mp3 
C:\Users\user\Desktop\folder\100 speech.mp3
C:\Users\user\Desktop\folder\101 speech.mp3
C:\Users\user\Desktop\folder\102 speech.mp3
C:\Users\user\Desktop\folder\103 speech.mp3  
C:\Users\user\Desktop\folder\104 speech.mp3
C:\Users\user\Desktop\folder\105 speech.mp3
C:\Users\user\Desktop\folder\106 speech.mp3
C:\Users\user\Desktop\folder\107 speech.mp3
C:\Users\user\Desktop\folder\108 speech.mp3
C:\Users\user\Desktop\folder\109 speech.mp3
C:\Users\user\Desktop\folder\11 speech.mp3 

尝试按日期或大小排序不是解决方案。

更新 所有以前的答案都很好:

l = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=len)
l = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=lambda x: int(os.path.basename(x).split(' ')[0]))

def get_key(fp):
    filename = os.path.splitext(os.path.basename(fp))[0]
    int_part = filename.split()[0]
    return int(int_part)

l = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=get_key)

【问题讨论】:

    标签: python list sorting glob


    【解决方案1】:

    一般的答案是用re.match() 捕获数字,然后用int() 将该数字(字符串)转换为整数。使用这些数字对带有sorted()的文件进行排序

    代码

    import re 
    import math
    from pathlib import Path 
    
    file_pattern = re.compile(r'.*?(\d+).*?')
    def get_order(file):
        match = file_pattern.match(Path(file).name)
        if not match:
            return math.inf
        return int(match.groups()[0])
    
    sorted_files = sorted(files, key=get_order)
    

    示例输入

    考虑在文件名的任何部分中具有一个整数数字的随机文件:

    ├── 012 some file.mp3
    ├── 1 file.txt
    ├── 13 file.mp3
    ├── 2 another file.txt
    ├── 3 file.csv
    ├── 4 file.mp3
    ├── 6 yet another file.txt
    ├── 88 name of file.mp3
    ├── and final 999.txt
    ├── and some another file7.txt
    ├── some 5 file.mp3
    └── test.py
    

    示例输出

    get_order() 可用于对文件进行排序,当传递给 key 参数中的 sorted() 内置函数时

    In [1]: sorted(files, key=get_order)
    Out[1]:
    ['C:\\tmp\\file_sort\\1 file.txt',
     'C:\\tmp\\file_sort\\2 another file.txt',
     'C:\\tmp\\file_sort\\3 file.csv',
     'C:\\tmp\\file_sort\\4 file.mp3',
     'C:\\tmp\\file_sort\\some 5 file.mp3',
     'C:\\tmp\\file_sort\\6 yet another file.txt',
     'C:\\tmp\\file_sort\\and some another file7.txt',
     'C:\\tmp\\file_sort\\012 some file.mp3',
     'C:\\tmp\\file_sort\\13 file.mp3',
     'C:\\tmp\\file_sort\\88 name of file.mp3',
     'C:\\tmp\\file_sort\\and final 999.txt',
     'C:\\tmp\\file_sort\\test.py']
    

    简短说明

    • re.compile 用于小幅提升速度(如果匹配多次相同的模式)
    • re.match 用于匹配正则表达式模式
    • 在正则表达式模式中,.*? 表示任意字符 (.),零次或多次 (*) 非贪婪 (?)。 \d+ 匹配任何数字一次或多次,括号仅捕获与groups() 列表匹配的内容。
    • 如果不匹配(文件中没有数字),match 将为Noneget_order 为无穷大;这些文件是任意排序的,但可以为这些文件添加逻辑(在此问题中未询问)。
    • sorted() 函数采用 key 参数,它应该是可调用的,它采用一个参数:列表中的项目。在这种情况下,它将是这些文件字符串之一(完整文件路径)
    • Path(file).name 只是从完整文件路径中获取文件名部分(不带后缀)。

    【讨论】:

      【解决方案2】:

      试试这个:

      import glob
      import os
      files = sorted(glob.glob(f'{os.getcwd()}/*.txt'), key=len)
      print(files)
      

      【讨论】:

      • 这项工作很棒,您能解释一下为什么使用 len 可以正常工作吗?
      • 因为C:\Users\user\Desktop\folder\10 speech.mp3C:\Users\user\Desktop\folder\1 speech.mp3 长,它会排序相同长度的。
      【解决方案3】:

      给你:

      import os, glob
      
      def get_key(fp):
          filename = os.path.splitext(os.path.basename(fp))[0]
          int_part = filename.split()[0]
          return int(int_part)
      
      files = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=get_key)
      

      【讨论】:

        【解决方案4】:

        您似乎在拆分完整路径,而不是基本名称。你可以试试这个:

        files = sorted(glob.glob(f'{os.getcwd()}/*.mp3'), key=lambda x: int(os.path.basename(x).split(' ')[0]))
        

        【讨论】:

        • 这将给我在更新问题中显示的相同内容
        • 也许你必须把它转换成 int(): key=lambda x: int(os.path.basename(x).split(' ')[0]))
        • 是的,我的错。之前的所有答案都有效,但这与我正在做的最相似。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-04
        • 2011-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多