如何按排序顺序遍历字典键

How to traverse dictionary keys in sorted order

我正在阅读一个 cfg 文件,并收到每个部分的字典。所以,例如:

配置文件:

[General]
parameter1="Param1"
parameter2="Param2"

[FileList]
file001="file1.txt"
file002="file2.txt" ......

我将 FileList 部分存储在名为 section 的字典中。在这个例子中,我可以访问 "file1.txt" 作为 test = section["file001"],所以 test == "file1.txt"。要一个接一个地访问 FileList 的每个文件,我可以尝试以下操作:

for i in range(1, (number_of_files + 1)):
    access_key = str("file_00" + str(i))
    print(section[access_key])

这是我目前的解决方案,但我一点都不喜欢。首先,它在python中看起来有点乱,但是当配置中列出的文件超过 9 个时,我也会遇到问题。

我也可以这样做:

for i in range(1, (number_of_files + 1)):
    if (i <= 9):
        access_key = str("file_00" + str(i))
    elif (i > 9 and i < 100):
        access_key = str("file_0" + str(i))
    print(section[access_key])

但我不想从那开始,因为它变得更糟。所以我的问题是:按顺序遍历所有文件名的正确且相对干净的方法是什么?我绝对需要循环,因为我需要对每个文件执行一些操作。

使用零填充生成文件编号(例如,请参阅此 SO 问题答案:)。这样您就不必自己编写通过数字翻转移动的逻辑——您可以使用 built-in Python 功能为您完成。如果您使用的是 Python 3,我还建议您尝试 f-strings(上面 link 中的建议解决方案之一)。他们很棒!

如果我们可以假设文件编号为三位数字,那么您可以执行以下操作来实现零填充。以下全部 returns "015".

i = 15

str(i).zfill(3)
# or
"%03d" % i 
# or
"{:0>3}".format(i)
# or
f"{i:0>3}"

首先查看您实际拥有的钥匙,而不是猜测它们可能是什么。你需要过滤掉符合你pattern的,然后按照数字部分排序。

keys = [key for key in section.keys() if key.startswith('file') and key[4:].isdigit()]

您可以添加其他条件,例如 len(key) > 4,或完全删除条件。也可以考虑学习正则表达式,让校验更优雅

要在不考虑填充的情况下对名称进行排序,您可以这样做

keys = sorted(keys, key=lambda s: int(s[4:]))

您也可以尝试像 natsort 这样的库,它将更普遍地处理自定义排序键。

现在你可以遍历键并做任何你想做的事情了:

for key in sorted((k for k in section if k.startswith('file') and k[4:].isdigit()), key=lambda s: int(s[4:])):
    print(section[key])

以下是配备 renatsort 的解决方案可能如下所示:

import re
from natsort import natsorted

pattern = re.compile(r'file\d+')
for key in natsorted(k for k in section if pattern.fullmatch(k)):
    print(section[key])