在循环中生成列表字典 (3.2.3)
Generating dictionary of lists in a loop (3.2.3)
我需要创建一个字典,其中键是一个字符串,值是一个列表。诀窍是我需要循环执行。
目前我的最小化代码如下所示:
for elem in xmlTree.iter():
# skipping root element
if elem.tag == xmlTree.getroot().tag:
continue
# this is supposed to be my temporary list
tmpList = []
for child in elem:
tableWColumns[elem.tag] = tmpList.append(child.tag)
print(tableWColumns)
这仅打印在上次迭代中创建的列表。
问题显然在于每当我更改列表时,它的所有引用也会随之更改。我用谷歌搜索了那个。我没有用谷歌搜索过的是在使用循环时如何处理它。
当我想保留列表时,我应该使用的解决方案是将它复制到其他列表,然后我可以在不丢失数据的情况下更改原始列表。当我基本上需要动态地执行此操作时,我不知道该怎么做。
此外,我仅限于使用标准库。
问题是因为你在每次迭代中创建 tmpList = []
列表并将其放入 []
。所以 python 在每次迭代中用旧的替换新的,因此你查看列表中的最后一次迭代结果。
您可以使用 collections.defaultdict
:
from collections import defaultdict
d=defaultdict(list)
for elem in xmlTree.iter():
# skipping root element
if elem.tag == xmlTree.getroot().tag:
continue
# this is supposed to be my temporary list
for child in elem:
d[elem.tag].append(child.tag)
print(tableWColumns)
或者你可以使用dict.setdefault
方法:
d={}
for elem in xmlTree.iter():
# skipping root element
if elem.tag == xmlTree.getroot().tag:
continue
# this is supposed to be my temporary list
for child in elem:
d.setdefault(elem.tag,[]).append(child.tag)
print(tableWColumns)
另请注意,@abarnert 说 tmpList.append(child.tag)
将 return None
。所以实际上在分配后 python 会将 None
分配给 tableWColumns[elem.tag]
.
这里的大问题是 tmpList.append(child.tag)
returns None
。事实上,Python return None
.
中几乎所有的变异方法
要解决这个问题,您可以进行突变,然后在单独的语句中插入值:
for child in elem:
tmpList.append(child.tag)
tableWColumns[elem.tag] = tmpList
… 或者一开始就不要尝试改变列表。例如
tableWColumns[elem.tag] = tmpList + [child.tag for child in elem]
这将解决您的所有值都是 None
的问题,但是您又遇到了一个新问题。如果任何标签出现不止一次,您只能从该标签的最后一个副本中获取子项,而不是从所有副本中获取。那是因为您每次都构建一个新列表,然后将 tableWColumns[elem.tag]
重新分配给该新列表,而不是修改其中的任何内容。
要解决该问题,您需要将现有值提取到 tmpList
而不是创建新值:
tmpList = tableWColumns.get(elem.tag, [])
tableWColumns[elem.tag] = tmpList + [child.tag for child in elem]
或者,如 所说,您可以使用 defaultdict
或 setdefault
方法来简化它。
我需要创建一个字典,其中键是一个字符串,值是一个列表。诀窍是我需要循环执行。
目前我的最小化代码如下所示:
for elem in xmlTree.iter():
# skipping root element
if elem.tag == xmlTree.getroot().tag:
continue
# this is supposed to be my temporary list
tmpList = []
for child in elem:
tableWColumns[elem.tag] = tmpList.append(child.tag)
print(tableWColumns)
这仅打印在上次迭代中创建的列表。
问题显然在于每当我更改列表时,它的所有引用也会随之更改。我用谷歌搜索了那个。我没有用谷歌搜索过的是在使用循环时如何处理它。
当我想保留列表时,我应该使用的解决方案是将它复制到其他列表,然后我可以在不丢失数据的情况下更改原始列表。当我基本上需要动态地执行此操作时,我不知道该怎么做。
此外,我仅限于使用标准库。
问题是因为你在每次迭代中创建 tmpList = []
列表并将其放入 []
。所以 python 在每次迭代中用旧的替换新的,因此你查看列表中的最后一次迭代结果。
您可以使用 collections.defaultdict
:
from collections import defaultdict
d=defaultdict(list)
for elem in xmlTree.iter():
# skipping root element
if elem.tag == xmlTree.getroot().tag:
continue
# this is supposed to be my temporary list
for child in elem:
d[elem.tag].append(child.tag)
print(tableWColumns)
或者你可以使用dict.setdefault
方法:
d={}
for elem in xmlTree.iter():
# skipping root element
if elem.tag == xmlTree.getroot().tag:
continue
# this is supposed to be my temporary list
for child in elem:
d.setdefault(elem.tag,[]).append(child.tag)
print(tableWColumns)
另请注意,@abarnert 说 tmpList.append(child.tag)
将 return None
。所以实际上在分配后 python 会将 None
分配给 tableWColumns[elem.tag]
.
这里的大问题是 tmpList.append(child.tag)
returns None
。事实上,Python return None
.
要解决这个问题,您可以进行突变,然后在单独的语句中插入值:
for child in elem:
tmpList.append(child.tag)
tableWColumns[elem.tag] = tmpList
… 或者一开始就不要尝试改变列表。例如
tableWColumns[elem.tag] = tmpList + [child.tag for child in elem]
这将解决您的所有值都是 None
的问题,但是您又遇到了一个新问题。如果任何标签出现不止一次,您只能从该标签的最后一个副本中获取子项,而不是从所有副本中获取。那是因为您每次都构建一个新列表,然后将 tableWColumns[elem.tag]
重新分配给该新列表,而不是修改其中的任何内容。
要解决该问题,您需要将现有值提取到 tmpList
而不是创建新值:
tmpList = tableWColumns.get(elem.tag, [])
tableWColumns[elem.tag] = tmpList + [child.tag for child in elem]
或者,如 defaultdict
或 setdefault
方法来简化它。