<p>您可以合并dict作为<code>itertools.groupby()</code>的后续操作。下面的解决方案很大程度上依赖于解包操作符,而解包操作符并不总是直观的,只能在一行中工作,但我会尽力解释</p>
<pre><code>from itertools import groupby
my_list = [
{'hostname': 'ABC', 'servicecheck': 'The roof is on fire', 'state': 'prettybad' },
{'hostname': 'DEF', 'servicecheck': 'The roof is on fire', 'state': 'prettybad' },
{'hostname': 'GHI', 'servicecheck': 'The roof is on fire', 'state': 'prettybad' },
{'hostname': 'ABC', 'servicecheck': 'The sky is blue', 'state': 'notsobad' },
{'hostname': 'ABC', 'servicecheck': 'The birds are pretty', 'state': 'prettybad' }
]
grouped_list = [
{**lst[0], 'hostname': [d['hostname'] for d in lst]}
for lst in [
list(group) for _, group in groupby(my_list, key=lambda d: (d['servicecheck'], d['state']))
]
]
# [
# {'hostname': ['ABC', 'DEF', 'GHI'], 'servicecheck': 'The roof is on fire', 'state': 'prettybad'},
# {'hostname': ['ABC'], 'servicecheck': 'The sky is blue', 'state': 'notsobad'},
# {'hostname': ['ABC'], 'servicecheck': 'The birds are pretty', 'state': 'prettybad'}
# ]
</code></pre>
<p>首先,我们使用列表理解来循环<code>itertools.groupby()</code>中的组。您可以提供一个自定义键(我已经这样做了),通过<code>'servicecheck'</code>和<code>'state'</code>键对相邻元素进行分组(如果您希望能够捕获和分组无序的事件,您可以首先调用<code>sorted()</code>并使用相同的键)</p>
<p>然后,我们使用另一个列表理解将组成每个组的<em>迭代器</em>从<code>groupby()</code>转换为<em>列表</em>,这样我们可以在表达式中多次使用它们,这是我们需要做的</p>
<p>接下来,我们为每个组创建一个dict。这不是dict理解,而是一个有趣的习惯用法,它使用解包操作符<code>**</code>将一个dict转换为另一个dict(基本上,编写dict文本,但从现有dict获取键和值)。因此表达式<code>{**lst[0]}</code>生成了一个新的dict,但复制了<code>lst[0]</code>中的键和值。请注意,除了<code>'hostname'</code>之外的所有键和值在组中的所有对象之间都是相同的</p>
<p>然后,我们在同一文本中覆盖<code>'hostname'</code>键,从而适应这种情况-在这里,我们只是从列表中拉出所有不同的主机名,并将它们粘贴到一个列表中,我们将其分配给原始主机名</p>
<p>所以这个表达式<code>{**lst[0], 'hostname': [d['hostname'] for d in lst]}</code>在功能上等同于</p>
<pre><code>{
'hostname': lst[0]['hostname'], # will be overwritten
'servicecheck': lst[0]['servicecheck'],
'state': lst[0]['state'],
'hostname': [d['hostname'] for d in lst] # overwrites the first one
}
</code></pre>
<p>我们对每个小组都这样做,以得到我们的答案</p>
<hr/>
<p>(如果希望输出中的第二项和第三项是字符串而不是单例列表,则可以替换</p>
<pre><code>[d['hostname'] for d in y]
</code></pre>
<p>与</p>
<pre><code>[d['hostname'] for d in y] if len(y) > 1 else y[0]['hostname']
</code></pre>
<p>)</p>