【问题标题】:Python: Redundancy when iterating through nested dictionaryPython:迭代嵌套字典时的冗余
【发布时间】:2016-01-14 09:36:04
【问题描述】:

我有一个嵌套字典,我正在尝试循环访问它以写入 excel 文件。

这是启动和创建嵌套字典的代码

def tree(): return defaultdict(tree)
KMstruct = tree()
for system in sheet.columns[0]:
if system.value not in KMstruct:
    KMstruct[system.value]
    for row in range(1,sheet.get_highest_row()+1):
        if sheet['A'+str(row)].value == system.value and sheet['B'+str(row)].value not in KMstruct:
            KMstruct[system.value][sheet['B'+str(row)].value]
            if sheet['B'+str(row)].value == sheet['B'+str(row)].value and sheet['C'+str(row)].value not in KMstruct:
                KMstruct[system.value][sheet['B'+str(row)].value][sheet['C'+str(row)].value]
                if sheet['C'+str(row)].value == sheet['C'+str(row)].value and sheet['D'+str(row)].value not in KMstruct:
                    KMstruct[system.value][sheet['B'+str(row)].value][sheet['C'+str(row)].value][sheet['D'+str(row)].value]
                    KMstruct[system.value][sheet['B'+str(row)].value][sheet['C'+str(row)].value][sheet['D'+str(row)].value] = [sheet['E'+str(row)].value]

这是我循环的代码:

for key in KMstruct.keys():
r += 1
worksheet.write(r, col,     key)
for subkey in KMstruct[key]:
    if currsubkeyval != subkey:
        r += 1
        worksheet.write(r, col,     key)
    r +=1
    worksheet.write(r, col, key + '\\' + subkey)
    for item in KMstruct[key][subkey]:
        if curritemval != item:
            r +=1
            worksheet.write(r, col, key + '\\' + subkey)
        for subitem in KMstruct[key][subkey][item]:
            r += 1
            worksheet.write(r, col, key + '\\' + subkey + '\\' + item)
            worksheet.write(r, col + 1, subitem)
            curritemval = item
            for finalitem in KMstruct[key][subkey][item][subitem]:
                r += 1
                worksheet.write(r, col, key + '\\' + subkey + '\\' + item + '\\' + subitem)
                worksheet.write(r, col + 1, KMstruct[key][subkey][item][subitem])

由于我是菜鸟,请耐心等待这段代码,我知道这不是那么漂亮。无论如何,我的问题是最后一个循环。我试图在KMstruct[key][subkey][item][subitem] 中获取字符串值,但循环变量lastitem 遍历键的字符串值的每个字符(注意:键subitem 包含字符串列表)。这意味着如果我只有一个要写入的值,它会被写入与字符串中的字符一样多的次数。

E.g.: value: apple 将在新的 excel 行上写入 5 次

我在这里做错了什么?

编辑:关于冗余的问题已经解决,但现在我需要了解在将我的最后一项(即我的字符串列表)分配给子项键时是否做错了。

【问题讨论】:

    标签: python excel dictionary tree iteration


    【解决方案1】:

    问题是在 Python 中 str 也是一个可迭代对象,例如:

    >>> for s in 'hello':
    ...    print(s)
    
    h
    e
    l
    l
    o
    

    因此,您要么需要避免在值为 str 时进行迭代,要么将 str 包装在另一个可迭代对象中(例如 list),以便以相同的方式处理它。这会因您构建代码的方式而变得有些困难。例如:

    for key in KMstruct.keys():
        for subkey in KMstruct[key]:
    

    ...可以写成:

    for key, value in KMstruct.items():
        for subkey, subvalue in value.items():
    

    ...在每个循环中为您提供 ,从而可以应用测试。

    for key, val in KMstruct.items():
    r += 1
    worksheet.write(r, col,     key)
    
    for subkey, subval in val.items():
        if currsubkeyval != subkey:
            r += 1
            worksheet.write(r, col,     key)
        r +=1
        worksheet.write(r, col, key + '\\' + subkey)
    
        for item, itemval in subval.items():
            if curritemval != item:
                r +=1
                worksheet.write(r, col, key + '\\' + subkey)
    
            for subitem, subitemval in itemval.items():
                r += 1
                worksheet.write(r, col, key + '\\' + subkey + '\\' + item)
                worksheet.write(r, col + 1, subitem)
                curritemval = item
    
                # I am assuming at this point subitemval is either a list or a str?
                if type(subitemval) == str:
                    # If it is, wrap it as a list, so the next block works as expected
                    subitemval = [subitemval] 
    
                for finalitem in subitemval:
                    r += 1
                    worksheet.write(r, col, key + '\\' + subkey + '\\' + item + '\\' + subitem)
                    worksheet.write(r, col + 1, finalitem) # This should be finalitem, correct?
    

    在这里,我们测试subitemval 的类型,如果是str,则将其包装在[str] 列表中,以便以下块按预期进行迭代。还有一个明显的错误,您没有在最后一行输出finalitem。如果没有您的示例数据,就不可能对此进行测试,但它应该在功能上是等效的。

    【讨论】:

    • 效果很好,非常感谢!关于 subitemval 是列表还是 str 的问题,答案是 subitemval 应该是 str 的列表。所以我想要实现的是编写所有子项,即各个子项的最终项。你知道我应该怎么做吗?
    • 上面的代码应该可以做到这一点!类型检查应确保 subitemval 始终是一个列表,因此 for finalitem in subitemval 将正确地迭代它。
    • 不幸的是,情况并非如此,目前它只打印出第一个 subitemval。我怀疑在构建字典和分配子项时我做错了什么。你介意看看那部分吗?
    • 完全没有,将你的数据结构/创建添加到问题中,我会看看。
    • @Sajruss 稍后会看看。同时尝试通过打印每个级别的值来进行实验,例如print(subitemval) 查看值是否符合您的预期。
    【解决方案2】:

    您的直接问题是示例的最后一行应该是:

                    worksheet.write(r,col+1, finalitem)
    

    顺便说一句,如果您偶尔创建临时变量,您的代码会更容易阅读:

            subitemlist = KMstruct[key][subkey][item]
            for subitem in subitemlist:
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-21
      • 1970-01-01
      • 1970-01-01
      • 2019-08-05
      • 1970-01-01
      • 1970-01-01
      • 2021-11-29
      • 1970-01-01
      相关资源
      最近更新 更多