如何在有序字典中获得正确数量的子元素?

Posted

技术标签:

【中文标题】如何在有序字典中获得正确数量的子元素?【英文标题】:How to get correct number of sub elements in ordered dictionary? 【发布时间】:2021-10-21 15:09:07 【问题描述】:

我有以下 2 个类似的有序字典(即前面步骤的输出),唯一的区别是 dict1 只有一个名为 GROUP 的节点,dict2 有两个(0 和 1 类似图片中)

from collections import OrderedDict

dict1 = OrderedDict([('CATALOG', 
            OrderedDict([('GROUP', 
                OrderedDict([
                    ('ZONE', '4'), 
                    ('LIGHT', 'Mostly Shady'), 
                    ('PLANT', [
                        OrderedDict([
                            ('COMMON', 'Bloodroot'), 
                            ('BOTANICAL', 'Sanguinaria canadensis')]), 
                        OrderedDict([
                            ('COMMON', 'Columbine'), 
                            ('BOTANICAL', 'Aquilegia canadensis')])])]))]))])
                            
dict2 = OrderedDict([('CATALOG', 
            OrderedDict([('GROUP', [
                OrderedDict([
                    ('ZONE', '3'), 
                    ('LIGHT', 'Mostly Shady'), 
                    ('PLANT', [
                        OrderedDict([
                            ('COMMON', "Dutchman's-Breeches"), 
                            ('BOTANICAL', 'Dicentra cucullaria')]), 
                        OrderedDict([
                            ('COMMON', 'Ginger, Wild'), 
                            ('BOTANICAL', 'Asarum canadense')])])]), 
                OrderedDict([
                    ('ZONE', '4'), 
                    ('LIGHT', 'Mostly Sunny'), 
                    ('PLANT', [
                        OrderedDict([
                            ('COMMON', 'Marsh Marigold'), 
                            ('BOTANICAL', 'Caltha palustris')]), 
                        OrderedDict([
                            ('COMMON', 'Cowslip'), 
                            ('BOTANICAL', 'Caltha palustris')])])])])]))])

结构是这样的:

我在确定每个字典有多少组时遇到问题,我的尝试如下所示,显示 dict2 的正确组数为 2,但当只有一组时,dict1 显示为答案 3 .如果我使用循环打印每个组,dict2 打印 2 个orderedDict 是正确的,但dict1 打印其他不是GROUP 的子节点。我做错了什么。

>>> len(dict1['CATALOG']['GROUP'])
3
>>> len(dict2['CATALOG']['GROUP'])
2
>>> dict1['CATALOG']['GROUP'][0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 0
>>>
>>> dict2['CATALOG']['GROUP'][0]
OrderedDict([('ZONE', '3'), ('LIGHT', 'Mostly Shady')...
>>>
>>> dict2['CATALOG']['GROUP'][1]                     ...
OrderedDict([('ZONE', '4'), ('LIGHT', 'Mostly Sunny')...
>>>                                                  ...
>>> for group in dict1['CATALOG']['GROUP']:          
...  print(group)                                    
...                                                  
ZONE                                                 
LIGHT                                                
PLANT                                                
>>> for group in dict2['CATALOG']['GROUP']:          
...  print(group)                                    
...                                                  
OrderedDict([('ZONE', '3'), ('LIGHT', 'Mostly Shady')...
OrderedDict([('ZONE', '4'), ('LIGHT', 'Mostly Sunny')...

【问题讨论】:

dict1['CATALOG']['GROUP'] 是一个包含 3 个键的字典,dict2['CATALOG']['GROUP'] 是一个包含两个元素的列表。 顺便说一句,从 Python 3.6 开始,普通字典会记住它们的顺序,所以你不需要使用OrderedDict 感谢您的回答。因此,我需要确定字典何时只有键(将是一个 GROUP)以及何时是具有多个元素的列表(表示多个 GROUP)。我使用 OrderedDict 是因为上一步给出的输出不受我控制。 @GerCas 你想统计字典中的子元素吗?或者只是确定对象是否是列表? @Elan-R 我想知道字典中有多少节点GROUP。在@Barmar 的帮助下,我明白要做到这一点,我首先需要知道GROUP 是列表还是字典。知道了之后,我就可以统计出名为GROUP的节点数了。如果是 dict 长度 =1,如果是列表长度 = 该列表中的元素数。 【参考方案1】:

检查dictX['CATALOG']['GROUP'] 是否为列表。如果不是列表,则长度为 1。

group1_len = len(dict1['CATALOG']['GROUP']) if isinstance(dict1['CATALOG']['GROUP'], list) else 1
group2_len = len(dict2['CATALOG']['GROUP']) if isinstance(dict2['CATALOG']['GROUP'], list) else 1

如果您先将字典包装在一个列表中,它可能会进行所有进一步的处理。那么两个字典的结构就会相似,你就不需要继续使用条件了。

for d in (dict1, dict2):
    if not isinstance(d['CATALOG']['GROUP'], list):
        d['CATALOG']['GROUP'] = [d['CATALOG']['GROUP']]

【讨论】:

感谢您的回答,但 dict1dict2 是针对相同的先前过程生成的。一个名为 xmltodict 的库,它从 xml 文件中获取输入。似乎当文件只有一个 GROUP 时,生成字典值作为 OrderedDict,而不是像 dict1 中的 OrderedDict 列表 您可以使用isinstance() 来测试它是字典还是列表。如果是字典,那就只有一本。 优秀。这似乎对我有用,我试过测试是否是一个列表,dict1 给出falsedict2 给出true&gt;&gt;&gt; isinstance(dict1['CATALOG']['GROUP'], list) False &gt;&gt;&gt; isinstance(dict2['CATALOG']['GROUP'], list) True 优秀!!!然后你首先fix 字典的结构,然后len(dictX['CATALOG']['GROUP']) 将适用于任何类型的具有一个或多个组的字典。【参考方案2】:

dict1 的长度就是密钥本身。如果我们知道这个对象是Dict 类型,我们可以使用辅助方法来做一些工作。

您可以在开始时进行一些类型检查以确定对象的形状。这将告诉您基础形状是 Dict(又名 1 项)还是 List(又名,多个)。

# something with 1 item, dict rendering
dict1 = ...

# something with 2 items, list rendering
dict2 = ...

# helper method
def checkShape(dict):
    length = 0
    if isinstance(dict['CATALOG']['GROUP'], dict):
        # we know len is 1
        length = 1
    else:
        # we know len is >1
        length = len(dict['CATALOG']['GROUP'])
    return length

【讨论】:

太棒了!您的解决方案也可以正常工作。我只将参数更改为dictX,因为仅使用dict 会出错,因为它与isinstance(dictX,dict) 中预期的元素type 混淆。非常感谢

以上是关于如何在有序字典中获得正确数量的子元素?的主要内容,如果未能解决你的问题,请参考以下文章

如何有效地计算列中每个元素的子元素数量?

js中父元素如何获得元素的子元素么

CSS 可以检测元素的子元素数量吗?

jquery - 返回子元素的数量,但对于不同的父元素

插入排序算法--Java实现

1074. 元素和为目标值的子矩阵数量