有没有办法循环处理具有相似名称(数字差异)的字典中的文件?

时间:2019-07-30 09:29:15

标签: python python-3.x loops dictionary

我想知道是否可以在循环中使用字典中名称相似的文件。

我有这个字典:

dcm = {}
for filename in os.listdir('./GMATfiles'):
    if fnmatch.fnmatch(filename,'DCM_hydra*.txt'):
       dcm[filename[:11]] = os.path.normpath(''.join(['./GMATfiles', '/', filename]))
       #print(dcm)

#OUT_INPUT
out={}
for filename in os.listdir('./GMATfiles'):
    if fnmatch.fnmatch(filename,'Out_hydra*.txt'):
       out[filename[:11]] = os.path.normpath(''.join(['./GMATfiles', '/', filename]))
       #print(out) 
#MATRIX_INPUT 
mtr={}
for filename in os.listdir('./GMATfiles'):
    if fnmatch.fnmatch(filename,'matrizr_hydra*.txt'):
       mtr[filename[:15]] = os.path.normpath(''.join(['./GMATfiles', '/', filename]))
       #print(mtr)

我从这些词典中的每个词典中获得的名称都是相同的,除了数字(例如:DCM_hydra01,DCM_hydra02,DCM_hydra03等)

然后我需要在某些功能中使用字典中的这些文件:

IFOV1= gi.IFOV_generic(out['Out_hydra01'],mtr['matrizr_hydra01'], dcm['DCM_hydra01'],'ifovfile_hydra1', endpoint)
IFOV2= gi.IFOV_generic(out['Out_hydra02'],mtr['matrizr_hydra02'], dcm['DCM_hydra02'],'ifovfile_hydra2',endpoint)
.
.
.

有没有一种方法可以编写循环,而无需逐个编写这些IFOV函数?

有人已经告诉我使用zip()这样:

dcm = {'f1': 'path_to_file'}
out = {'f1': 'path_to_file'}
mtr = {'f1': 'path_to_file'}

IFOV = []

for d, o, m in zip(dcm, out, mtr):
    IFOV.append(
        gi.IFOV_generic(out[o], mtr[m], dcm[d], endpoint)
    )

但是我需要获得文件名('ifovfile_hydra *'),并且我不确定此代码是否可以做到这一点。

2 个答案:

答案 0 :(得分:0)

字典中的“索引”是一个字符串,是的,我们可以使用它来做任何事情!

给出的代码片段应能按预期工作,并且实际上不会在字符串中插入数字!最终名称的一个小修正:

dcm = {'f1': 'path_to_file'}
out = {'f1': 'path_to_file'}
mtr = {'f1': 'path_to_file'}

IFOV = []

for d, o, m in zip(dcm, out, mtr):
    IFOV.append(
        gi.IFOV_generic(out[o], mtr[m], dcm[d], 'ifovfile_hydra'+o[-2:], endpoint)
    )

默认情况下,字典仅在键上进行迭代。您可以使用文件名。

通过压缩,可以将第一个字典的第一个键与第二个字典的第一个键和第三个字典的第一个键组合。

然后for循环遍历这3个元素的组,并将它们的内容放入单独的变量中。它们仍然包含各自的文件名。

'ifovfile_hydra'+o[-2:]-o[-2:]从字符串o中获取最后两个字符('Out_hydra01','Out_hydra02'...)。

该代码的唯一问题是文件的顺序是否不正确(例如,第一字典顺序为03、01、02,而第二和第三则为“正确”)。可以通过制作dmc = dict(sorted(dcm.items())来解决此问题,依此类推-在较新的Python中,字典的内容保持插入顺序,因此此代码段将dict转换为列表,对其进行排序,然后将其转换回dict(将在依字母顺序排列,所以“ a10” <“ a2”,但是用0填充的数字是正确的:“ a10”>“ a02”)。


另一件事是真正在字符串中填写数字。

for i in range(1, len(dcm)):
    IFOX.append(
        gi.IFOV_generic(out['Out_hydra{:02d}'.format(i)], met['matrizr_hydra{:02d}'.format(i)], dcm['DCM_hydra{:02d}'.format(i)],'ifovfile_hydra{:02d}'.format(i),  endpoint)
    )

:02d部分表示它是0填充到2位数字。

答案 1 :(得分:0)

我建议您直接在读取文件的同一循环中填充IFOV。但是,如果您不想这样做,那么建议您创建一个字典,而只循环遍历这些文件一次:

from collections import defaultdict
from pathlib import Path

# If you're not on python 3.7, replace this with a function that makes a dict
@dataclass
class GmatFiles:
    dcm: str = ""
    out: str = ""
    mtr: str = ""


files = defaultdict(GmatFiles)
for filepath in Path("./GMATfiles".glob("*.txt"):
    if fnmatch.fnmatch(filename,'DCM_hydra*.txt'):
        files[filepath.name[9:11]].dcm = filepath
    elif nmatch.fnmatch(filename,'Out_hydra*.txt'):
        files[filepath.name[9:11]].out = filepath
    elif fnmatch.fnmatch(filename,'matrizr_hydra*.txt'):
        files[filepath.name[13:15]].mtr = filepath

IFOV = []  
for item in files.values():
    IFOV.append(
        dcm = files[k
        gi.IFOV_generic(item.out, item.mtr, item.dcm, endpoint)
    )