【问题标题】:globbing a range with padded 0's- python用填充的 0's-python 覆盖一个范围
【发布时间】:2014-04-07 18:29:27
【问题描述】:

关于在 python 中通配的快速问题。

我有一个文件目录,其中包含“sync_0001.tif”、“sync_0002.tif”、...、“sync_2400.tif”。我想获得这些文件的 3 个子集列表:1 个用于前 800 个文件,第二个 800 个文件,最后 800 个文件。唯一的问题是数字前的 0。我无法找出获取这些列表的正确方法。第三个列表很简单,因为没有 0 填充任何这些文件 (s3=glob.glob('sync_[1601-2400].tif')。另外两个比较棘手,因为前面 0 的数量各不相同。

我试过这个,但得到“错误的字符范围”,我猜是因为 0:

s1 = glob.glob('sync_' + '{[0001-0009], [0010-0099], [0100-0800]}' + '.tif')
s2 = glob.glob('sync_' + '{[0801-0999], [1000-1600]}' + '.tif')

然后我尝试像这样将 0 移到前面,但得到一个空列表:

s1 = glob.glob('sync_' + '{000[1-9], 00[10-99], 0[100-800]}' + '.tif')

实现这三个列表的最佳方法是什么?我开始认为我把整个 glob 的事情搞错了,所以如果有人能解释一下,那就太好了。谢谢!

【问题讨论】:

标签: python glob


【解决方案1】:

支撑glob.glob() 函数的fnmatch module 对您的任务来说还不够复杂。

只需获取所有个文件名并在排序后对其进行分区:

filenames = sorted(glob.glob('sync_[0-9][0-9][0-9][0-9].tif'))

这是有效的,因为您的数字是填充的,因此可以按字典顺序排序。然后对它们进行分区:

s1 = [f for f in filenames if 0 < int(f[5:9]) <= 800]
s2 = [f for f in filenames if 800 < int(f[5:9]) <= 1600]
s3 = [f for f in filenames if 1600 < int(f[5:9]) <= 2400]

无论如何,目录 I/O 将是最慢的。您可以通过只循环一次并交换您附加的内容来提高效率:

target = s1 = []
s2 = []
s3 = []
for f in filenames:
    num = int(f[5:9])
    if num > 800:
        target = s2
    elif num > 1600:
        target = s3
    target.append(f)

但对于这样的任务,坚持使用更简单的列表推导也很好。

【讨论】:

  • 并非所有文件都是sync_,有些是sync999,有些是sync 000;除非这是原始问题中的错字。
  • @BurhanKhalid:样本尝试使用我在回答中使用的模式。我认为例外是拼写错误。
  • @BurhanKhalid 是的,对不起。那是个错误。谢谢你们的回答!我会接受这个答案,因为它接近我原来的解决方案,我只需 3 行就可以完成
【解决方案2】:

最好的办法就是:

  1. glob 所有以sync 开头的文件
  2. 按数字组件对列表进行排序
  3. 将其分成 800 个块

既然你已经知道了 globbing,剩下的就是:

import glob
import re
from itertools import izip_longest

# https://docs.python.org/2/library/itertools.html#recipes
def grouper(iterable, n, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)


def sorter(x):
    return int(re.search('(\d+)',x).groups()[0])

files = glob.glob('sync*.tif')
sorted_files = sorted(files, key=sorter)
in_batches = list(grouper(sorted_files, 800))

由于模式始终为sync_(在您编辑后),您可以将上面的代码简化为以下内容:

files = glob.glob('sync_*.tif')
sorted_files = sorted(files, key=lambda x: int(x.split('_')[1]))
in_batches = list(grouper(sorted_files, 800))

【讨论】:

  • 谢谢。这也是一个可行的解决方案。我尝试投票但没有足够的声誉。再次感谢
猜你喜欢
  • 2019-08-17
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
  • 1970-01-01
  • 1970-01-01
  • 2019-02-22
  • 2019-11-11
  • 2014-10-24
相关资源
最近更新 更多