如何按排序顺序遍历字典键
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])
以下是配备 re
和 natsort
的解决方案可能如下所示:
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])
我正在阅读一个 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])
以下是配备 re
和 natsort
的解决方案可能如下所示:
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])