2010-07-04 143 views
1

假设我有一个文件名列表:[exia.gundam, dynames.gundam, kyrios.gundam, virtue.gundam][exia.frame, exia.head, exia.swords, exia.legs, exia.arms, exia.pilot, exia.gn_drive, lockon_stratos.data, tieria_erde.data, ribbons_almark.data, otherstuff.dada]Python:在列表中找到匹配扩展名或带有匹配名称的扩展名的文件

在一次迭代中,我想要所有* .gundam或* .data文件,而另一个我想将exia。*文件分组。除了遍历列表并将每个元素放入字典之外,做这件事最简单的方法是什么?

这是我脑子里想的:

def matching_names(files): 
    ''' 
    extracts files with repeated names from a list 

    Keyword arguments: 
    files - list of filenames 

    Returns: Dictionary 
    ''' 

    nameDict = {} 
    for file in files: 
     filename = file.partition('.') 
     if filename[0] not in nameDict: 
      nameDict[filename[0]] = [] 
     nameDict[filename[0]].append(filename[2]) 

    matchingDict = {} 
    for key in nameDict.keys(): 
     if len(nameDict[key]) > 1: 
      matchingDict[key] = nameDict[key] 
    return matchingDict 

好吧,假设我要使用,有一个简单的方法来反转,并有文件扩展名的关键,而不是叫什么名字?

回答

2

在我的第一个版本中,它看起来像我误解了你的问题。所以,如果我有这个正确的,你正在处理一个文件列表,以便您可以轻松地访问所有的文件名与给定的扩展名,或所有文件名与给定的基础(“基地”是期)?

如果是这样的话,我建议是这样的:

from itertools import groupby 

def group_by_name(filenames): 
    '''Puts the filenames in the given iterable into a dictionary where 
    the key is the first component of the filename and the value is 
    a list of the filenames with that component.''' 
    keyfunc = lambda f: f.split('.', 1)[0] 
    return dict((k, list(g)) for k,g in groupby(
       sorted(filenames, key=keyfunc), key=keyfunc 
      )) 

例如,给出的列表

>>> test_data = [ 
... exia.frame, exia.head, exia.swords, exia.legs, 
... exia.arms, exia.pilot, exia.gn_drive, lockon_stratos.data, 
... tieria_erde.data, ribbons_almark.data, otherstuff.dada 
... ] 

该功能会产生

>>> group_by_name(test_data) 
{'exia': ['exia.arms', 'exia.frame', 'exia.gn_drive', 'exia.head', 
      'exia.legs', 'exia.pilot', 'exia.swords'], 
'lockon_stratos': ['lockon_stratos.data'], 
'otherstuff': ['otherstuff.dada'], 
'ribbons_almark': ['ribbons_almark.data'], 
'tieria_erde': ['tieria_erde.data']} 

如果你想索引文件名的扩展名,而不是轻微的修改将为你做到这一点:

def group_by_extension(filenames): 
    '''Puts the filenames in the given iterable into a dictionary where 
    the key is the last component of the filename and the value is 
    a list of the filenames with that extension.''' 
    keyfunc = lambda f: f.split('.', 1)[1] 
    return dict((k, list(g)) for k,g in groupby(
       sorted(filenames, key=keyfunc), key=keyfunc 
      )) 

唯一的区别是在keyfunc = ...线,在那里我改变的关键,从0到1例:

>>> group_by_extension(test_data) 
{'arms': ['exia.arms'], 
'dada': ['otherstuff.dada'], 
'data': ['lockon_stratos.data', 'ribbons_almark.data', 'tieria_erde.data'], 
'frame': ['exia.frame'], 
'gn_drive': ['exia.gn_drive'], 
'head': ['exia.head'], 
'legs': ['exia.legs'], 
'pilot': ['exia.pilot'], 
'swords': ['exia.swords']} 

如果你想同时获得这两个集团,不过,我认为避免列表理解会更好,因为它只能以某种方式处理它们,它不能一次构建两种不同的字典。

from collections import defaultdict 
def group_by_both(filenames): 
    '''Puts the filenames in the given iterable into two dictionaries, 
    where in the first, the key is the first component of the filename, 
    and in the second, the key is the last component of the filename. 
    The values in each dictionary are lists of the filenames with that 
    base or extension.''' 
    by_name = defaultdict(list) 
    by_ext = defaultdict(list) 
    for f in filenames: 
     name, ext = f.split('.', 1) 
     by_name[name] += [f] 
     by_ext[ext] += [f] 
    return by_name, by_ext 
+0

我没事通过列表迭代,但我想知道是否有更通用的(和简单的)解决方案。所以,如果我要将.gundam的格式更改为.flag,我可以使用相同的代码。我可以迭代列表并手动将它们添加到地图,以根据文件名的第一部分或第二部分查看匹配的内容,但这会导致更多的代码。 – 2010-07-04 03:44:32

+0

好吧,我想也许我编辑版本中的最后一个代码示例更符合您的需求。如果所有的条件都指定了文件名的开头或结尾,那么可以使用'startswith'和'endswith'字符串方法来代替正则表达式,这可能会节省一点计算时间,但代码会更长(但如果你愿意,我也可以编辑这种方式)。 – 2010-07-04 03:51:39

+0

@Setsuna:嗯,我认为你可以在目录上使用os.listdir(path)迭代,并获得所有可用的扩展,然后,用这个列表你可以像David说的那样对它们进行分组。 – 2010-07-04 04:00:34

0

我不知道如果我完全明白你希望做什么,但如果我理解正确的是这样的事情可能工作:

from collections import defaultdict 
files_by_extension = defaultdict(list) 

for f in files: 
    files_by_extension[ f.split('.')[1] ].append(f) 

这是创建通过键控哈希文件扩展名并通过在单个遍中遍历列表来填充它。

0

假设例如您要为结果文件名列表的列表,通过任一分机或ROOTNAME分组:

import os.path 
import itertools as it 

def files_grouped_by(filenames, use_extension=True): 
    def ky(fn): return os.path.splitext(fn)[use_extension] 
    return [list(g) for _, g in it.groupby(sorted(filenames, key=ky), ky)] 

现在files_grouped_by(filenames, False)将返回列出了ROOTNAME分组列表中,而如果第二论点是真的或缺席的分组将通过扩展。

如果你想,而不是一个字典,是无论rootnames或扩展和值的文件名的对应列表按键,这种方法颇为相似:

import os.path 
import itertools as it 

def dict_files_grouped_by(filenames, use_extension=True): 
    def ky(fn): return os.path.splitext(fn)[use_extension] 
    return dict((k, list(g)) 
       for k, g in it.groupby(sorted(filenames, key=ky), ky)] 
相关问题