【问题标题】:How to group dicts (compare dicts) based on all the keys?如何根据所有键对字典进行分组(比较字典)?
【发布时间】:2019-07-26 18:28:18
【问题描述】:

我正在编写一个 python 脚本,它首先解析“n”个 xml,并创建一个 dict 的 dict,其键值是 xml 属性(在嵌套的 dicts 内)。 现在,我想对存储的这些嵌套字典进行分组,以了解哪些 xml 是相同的并且可以分组到同一个组中。 我想要一些 pythonic 的方式来分组相同的字典,其中每个字典碰巧有相同的键。

  • 我尝试解析每个字典并从值创建一个字符串。 将此字符串存储在 dict 中,其中 key = string 和 value = xmlNames 列表。现在,当我转到下一个字典并形成字符串时,如果它已经存在于字典中,那么我只需将 xml 附加到这个字典的值。
  • 我认为基于 groupby() 或其他方法可以有更好的方法。
list_of_xmls =  ["a.xml", "b.xml", "c.xml", "d.xml"]
dictXml = dict()
for xml in list_of_xmls:
    dictXml[xml] = parseXml(xml)   # Returns dict by parsing xml (key-value)

# parseXml(xml)
# It parses xml and returns dict like:
dict for a.xml = {"config":"4", "location":"C:\\xyz", "Group":"amcat"}
dict for b.xml = {"config":"4", "location":"C:\\xyz", "Group":"amcat"}
dict for c.xml = {"config":"5", "location":"C:\\mno", "Group":"alien"}
dict for d.xml = {"config":"5", "location":"C:\\mno", "Group":"alien"}

# Supoose, a.xml and b.xml have same values for all keys
# Same for c.xml and d.xml
# So, I should have two groups (a.xml, b.xml) and (c.xml, d.xml)
 ###########Some processing on the above dict ######

finalOutput = [["a.xml", "b.xml], ["c.xml", "d.xml"]]


输出应该是可以合并的组列表(基本上是列表列表)。

此外,dictXml 可以是任何其他数据结构,也可以是字典列表。 有什么想法吗?

基本上,整个想法都给出了一个 xml 列表,我需要根据其中的键值来确定哪些 xml 是相同的。在某个列表中对相同的 xml 进行分组,并对每个组进行处理。

【问题讨论】:

  • parseXml 长什么样子?
  • 它适用于内部的某些架构。但是,它在处理完 xml 后最终返回一个带有键和值的 dict。没有任何其他细节。此外,无法更改 parseXML。
  • 那个字典看起来怎么样?最终期望的输出是什么?视觉示例将不胜感激
  • 感谢 Devesh 的关注。更新了代码中的 parseXml。希望对您有所帮助。
  • 您希望最终输出的样子如何?

标签: python python-2.7 list dictionary itertools


【解决方案1】:

您可以使用itertools.groupby (doc) 进行分组:

list_of_xmls =  ["a.xml", "b.xml", "c.xml", "d.xml"]

dictXml = {
'a.xml': {"config":"4", "location":"C:\\xyz", "Group":"amcat"},
'c.xml': {"config":"5", "location":"C:\\mno", "Group":"alien"},
'b.xml': {"config":"4", "location":"C:\\xyz", "Group":"amcat"},
'd.xml': {"config":"5", "location":"C:\\mno", "Group":"alien"},
}

from itertools import groupby
from operator import itemgetter

out = []
f = itemgetter(1)
s = sorted([(k, [i for i in v.items()]) for k, v in dictXml.items()], key=f)
for _, g in groupby(s, f):
    out.append([i[0] for i in g])

print(out)

打印:

[['a.xml', 'b.xml'], ['c.xml', 'd.xml']]

【讨论】:

  • 感谢您的回答。你能回答一下python 2.7或更低版​​本吗?它说:Python 版本
  • @PeXXeR 更新了我的答案,用 Python 2.7.15 测试了它
  • 非常感谢您在这里的快速帮助。我可以再要求你一件事吗?我几乎无法理解这里发生了什么。你能简单解释一下吗?我要求这是在分析此之后确定在时间复杂度方面是否有更好的方法,或者您的方法可能是最好的方法。
  • @PeXXeR 由于 sorted() 函数,复杂度为 O(n logn)。首先,我们按照从dictXml.values 创建的列表对dictXml 进行排序。然后我们在这个排序列表上应用itertools.groupby 并从每个组中提取键。
【解决方案2】:

试试这个,首先我只将 xml 名称和它所在的组放入一个元组列表中,然后应用这个分组算法Group list by values

dictXml = {"a.xml":{"Group":"a"}, "b.xml":{"Group":"b"}, "c.xml":{"Group":"b"}, "d.xml":{"Group":"d"}}

xml_group_list = [(xml, xml_dic["Group"]) for xml, xml_dic in dictXml.items()]
values = set(map(lambda x: x[1], xml_group_list))
newlist = [[y[0] for y in xml_group_list if y[1] == x] for x in values]
print(newlist)

输出:

[['a.xml'], ['b.xml', 'c.xml'], ['d.xml']]

【讨论】:

  • 谢谢。我不是python专家。但是,xml 恰好有大约 70 个键。那么,在这种情况下如何使用代码呢?你能帮忙吗?
  • dictXml替换a
  • 还删除了第一行,这只是一个示例。从xml_group_list... 开始
【解决方案3】:

我有另一种方法可以解决您的问题。 由于我不知道 parseXML(),所以决定采用 predefine_dict。希望你能理解。 你可以用 parseXML(xml) 替换predefined_dict[xml]

list_of_xmls =  ["a.xml", "b.xml", "c.xml", "d.xml"]
predefined_dict = {"a.xml":{"name":"mice", "surename":"dine"},
                     "b.xml":{"name":"akks", "surename":"john"}, 
                     "c.xml":{"name":"mice", "surename":"dine"},
                     "d.xml":{"name":"akks", "surename":"john"}}
dictXml = dict()
finalOutput =[]
temp_dict={}
for xml in list_of_xmls:
    temp = tuple([i for i in predefined_dict[xml].values()])
    print(temp)
    try:
        dictXml[temp].append(xml)
    except KeyError:
        dictXml[temp]= [xml]

print(dictXml)
for value in dictXml.values():
    finalOutput.append(value)
print("finalOutput", finalOutput)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 2010-12-07
    • 1970-01-01
    • 2023-01-17
    • 1970-01-01
    • 2017-03-09
    相关资源
    最近更新 更多