[英]Python: Redundancy when iterating through nested dictionary
I have a nested dictionary which I am trying to loop through in order to write to an excel file. 我有一个嵌套的字典,正在尝试遍历以便写入excel文件。
This is the code which initiates and creates the nested dictionary 这是启动和创建嵌套字典的代码
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]
This is the code where I loop through it: 这是我遍历的代码:
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])
Bear with me on this code since I am a noob, I am aware that this is not so beautiful. 因为我是菜鸟,所以请耐心等待这段代码,我知道这不是那么漂亮。 Anyhow, my problem is the last loop.
无论如何,我的问题是最后一个循环。 I am trying to take the string values in
KMstruct[key][subkey][item][subitem]
but the loop variable lastitem
goes through each char of key's string value (note: the key subitem
contains a list of strings). 我试图把在字符串值
KMstruct[key][subkey][item][subitem]
但循环变量lastitem
经过键的字符串值中的每个字符(注:关键subitem
包含字符串列表)。 This means that if I only have one value that is to be written, it gets written as many times as there are characters in the string. 这意味着,如果我只有一个要写入的值,则该值将被写入与字符串中的字符一样多的次数。
Eg: value: apple will be written on a new excel row 5 times 例如:值:苹果将在新的Excel行中写入5次
What am I doing wrong here? 我在这里做错了什么?
Edit: The issue on the redundancy has been solved but now I need to understand if I am doing something wrong when assigning my lastitem, ie my list of strings, to the subitem key. 编辑:关于冗余的问题已经解决,但现在我需要了解在将我的lastite(即我的字符串列表)分配给subitem键时是否做错了什么。
Your immediate problem is that the last line of your example should be: 您的直接问题是示例的最后一行应为:
worksheet.write(r,col+1, finalitem)
BTW, your code would be a lot easier to read if you created occasional temporary variables like: 顺便说一句,如果您创建了以下临时临时变量,则代码将更容易阅读:
subitemlist = KMstruct[key][subkey][item]
for subitem in subitemlist:
The problem is that in Python a str
is also an iterable, for example: 问题在于,在Python中,
str
也是可迭代的,例如:
>>> for s in 'hello':
... print(s)
h
e
l
l
o
So you either need to avoid iterating when the value is a str
, or wrap the str
in another iterable (eg a list
) so that it can be handled the same way. 因此,您要么需要避免在值是
str
时进行迭代,要么将str
包裹在另一个可迭代项(例如list
)中,以便可以用相同的方式进行处理。 This is made slightly difficult by how you are structuring your code. 通过如何构造代码,这变得有些困难。 For example, the following:
例如,以下内容:
for key in KMstruct.keys():
for subkey in KMstruct[key]:
...can be written as: ...可以写成:
for key, value in KMstruct.items():
for subkey, subvalue in value.items():
...giving you the value on each loop, making it possible to apply a test. ...在每个循环中为您提供值 ,从而可以进行测试。
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?
Here we test the type of the subitemval
and if it is a str
wrap it in a list [str]
so the following block iterates as expected. 在这里,我们测试
subitemval
的类型,如果它是str
,则将其包装在列表[str]
以便以下块按预期进行迭代。 There is also an apparent bug where you are not outputting the finalitem
on the last line. 还有一个明显的错误,即您没有在最后一行输出
finalitem
。 It's not posssible to test this without your example data but it should be functionally equivalent. 没有示例数据就无法对此进行测试,但是在功能上应该等效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.