<p>这是一种有点冗长(为了清楚起见)的方法:</p>
<pre><code>commands_by_category = {} # Initialize a dictionary
for command in config['commands'].items(): # for each block
category = command.get('category') # unpack categoy
cmd = command.get('cmd') # unpack command
cmds = commands_by_category.get(category, []) # Get the current list, or a default empty list
cmds.append(cmd) # Append to list.
commands_by_category[category] = cmds # Reassign back to the dict
</code></pre>
<p>注意:<a href="https://docs.python.org/3/tutorial/datastructures.html#more-on-lists" rel="nofollow noreferrer">^{<cd1>}</a>在列表上工作到位,因此您必须拉出当前列表,追加并重新分配它</p>
<p>另一个更简洁的选项是按行为分组:</p>
<pre><code>from itertools import groupby
from typing import Callable, Iterable
def group_by(iterable: Iterable, key: Callable) -> dict:
return {r[0]: list(r[1]) for r in groupby(sorted(iterable, key=key), key)}
group_by(config['commands'].items(), lambda x: x.get("category"))
</code></pre>
<p>这需要一点时间来解包,但它的作用如下:</p>
<ul>
<li>使用<a href="https://docs.python.org/3/howto/sorting.html#key-functions" rel="nofollow noreferrer">^{<cd2>}</a>和决定排序顺序的函数对iterable进行排序</李>
<li>这里提供的函数是获取类别值的<code>lambda</code>。这是自然的字母数字排序</李>
<li>然后使用<a href="https://docs.python.org/3/library/itertools.html#itertools.groupby" rel="nofollow noreferrer">^{<cd4>}</a>按相同的“键”函数分组</李>
<li>排序和分组后,对于结果iterable中的每个项,将类别指定为键,将结果列表指定为新字典中的值</李>
</ul>
<p>这里有一个小问题,它返回每个原始项目的完整dict,因此我们必须清理一些信息:</p>
<pre><code>sorted_commands = group_by(config['commands'].items(), lambda x: x.get("category"))
commands_by_category = {k: [i.get('command') for i in v] for k, v in sorted_commands.items()}
</code></pre>
<p>所有这些工作都是针对每个类别项,使用列表理解,获取字典列表,只保留命令名</p>
<p>行动中的完整示例:</p>
<pre><code>from itertools import groupby
from typing import Callable, Iterable
def group_by(iterable: Iterable, key: Callable) -> dict:
return {r[0]: list(r[1]) for r in groupby(sorted(iterable, key=key), key)}
ls = [{"category": "Information", "command": "info"},
{"category": "Owneronly", "command": "ban"},
{"category": "Owneronly", "command": "kick"},
]
expected = {
"Information": ["info"],
"Owneronly": ["ban", "kick"],
}
sorted_commands = group_by(ls, lambda x: x.get("category"))
commands_by_category = {k: [i.get('command') for i in v] for k, v in sorted_commands.items()}
commands_by_category == expected # True
</code></pre>
<p>这种方法虽然更密集,但功能更强大,并且利用了Python核心库。因此,我敢打赌它会更快</p>