假设我有一个文件名列表:[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]
。
在一次迭代中,我想拥有所有* .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
好吧,假设我必须使用它,是否有一种简单的方法来反转它并将文件扩展名作为键而不是名称?
答案 0 :(得分:2)
在我的第一个版本中,看起来我误解了你的问题。因此,如果我有正确的做法,那么您正在尝试处理文件列表,以便您可以轻松访问具有给定扩展名的所有文件名,或者具有给定基础的所有文件名(“base”是之前的部分周期)?
如果是这种情况,我会建议这样:
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
答案 1 :(得分:0)
我不确定我是否完全得到你想做的事情,但如果我理解正确的话可能会有效:
from collections import defaultdict
files_by_extension = defaultdict(list)
for f in files:
files_by_extension[ f.split('.')[1] ].append(f)
这是创建一个由文件扩展名键入的哈希值,并通过一次遍历列表来填充它。
答案 2 :(得分:0)
假设您希望将结果列为文件名列表,按扩展名或根名称分组:
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分组的列表列表,而如果第二个参数为True或不存在,则分组将是扩展名。
如果您想要一个字典,键是根名称或扩展名,而值是相应的文件名列表,方法非常相似:
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)]