如何对词典列表进行分组

2024-10-02 02:25:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我在谷歌上搜索过并尝试过各种方法(通常是在itertools.groupby())来实现这一点,但我显然没有正确的思考方法,所以我真的很高兴能得到一些帮助。我需要将主机名键合并到主机名列表中,所有其他键都匹配

所以我有一个目录:

MyList = [
    {'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' }
]

当其他键匹配时,我需要根据主机名合并它们,即:

GroupedList = [
    {'hostnames': ['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' }
]

Tags: the方法isondefcheckservicefire
2条回答
myList= [
    {'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' }
]
visitedIndexes  = {}
myListLen=len(myList)
for i in range(0,myListLen):
    if i in visitedIndexes:
        myList[i]=None
    else:
        visitedIndexes[i]=True
        #process the current index 
        for j in range(i+1,myListLen):
            if myList[i]["servicecheck"] == myList[j]["servicecheck"] and myList[i]["state"]==myList[j]["state"]:
                #group into the i index 
                if  isinstance(myList[i]["hostname"], str): 
                    myList[i]["hostname"]=[ myList[i]["hostname"]]
                myList[i]["hostname"].append(myList[j]["hostname"])
                visitedIndexes[j]=True
myListFinal=[obj  for obj in myList if obj!=None]
print(myListFinal)
                   

您可以合并dict作为itertools.groupby()的后续操作。下面的解决方案很大程度上依赖于解包操作符,而解包操作符并不总是直观的,只能在一行中工作,但我会尽力解释

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'}
# ]

首先,我们使用列表理解来循环itertools.groupby()中的组。您可以提供一个自定义键(我已经这样做了),通过'servicecheck''state'键对相邻元素进行分组(如果您希望能够捕获和分组无序的事件,您可以首先调用sorted()并使用相同的键)

然后,我们使用另一个列表理解将组成每个组的迭代器groupby()转换为列表,这样我们可以在表达式中多次使用它们,这是我们需要做的

接下来,我们为每个组创建一个dict。这不是dict理解,而是一个有趣的习惯用法,它使用解包操作符**将一个dict转换为另一个dict(基本上,编写dict文本,但从现有dict获取键和值)。因此表达式{**lst[0]}生成了一个新的dict,但复制了lst[0]中的键和值。请注意,除了'hostname'之外的所有键和值在组中的所有对象之间都是相同的

然后,我们在同一文本中覆盖'hostname'键,从而适应这种情况-在这里,我们只是从列表中拉出所有不同的主机名,并将它们粘贴到一个列表中,我们将其分配给原始主机名

所以这个表达式{**lst[0], 'hostname': [d['hostname'] for d in lst]}在功能上等同于

{
    '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
}

我们对每个小组都这样做,以得到我们的答案


(如果希望输出中的第二项和第三项是字符串而不是单例列表,则可以替换

[d['hostname'] for d in y]

[d['hostname'] for d in y] if len(y) > 1 else y[0]['hostname']

)

相关问题 更多 >

    热门问题