在循环中生成列表字典(3.2.3)

时间:2015-04-16 08:41:58

标签: python list dictionary iteration

我需要创建一个字典,其中键是字符串,值是列表。诀窍是我需要在循环中完成它。

我的最小化代码目前看起来像这样:

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)

这仅打印在上一次迭代中创建的列表。

问题显然在于每当我更改列表时,它的所有引用都会被更改。我用Google搜索了那个。我没有用Google搜索的是我在使用循环时如何处理它。

当我想保留列表时,我应该使用的解决方案是将其复制到其他列表,然后我可以更改原始列表而不会丢失数据。我不知道的是,当我基本上需要动态地执行此操作时,我该怎么做。

此外,我仅限于使用标准库。

2 个答案:

答案 0 :(得分:3)

问题在于你是在每次迭代中创建tmpList = []列表并将其放在[]。所以python在每次迭代中用new替换new,因此你看到最后的迭代结果你的清单。

相反,您可以使用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)将返回None。因此,在分配后,实际上python会将None分配给tableWColumns[elem.tag]

答案 1 :(得分:1)

这里的一个大问题是tmpList.append(child.tag)会返回None。实际上,Python中的几乎所有变异方法都返回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]

或者,正如Kasra's answer所述,您可以使用defaultdictsetdefault方法来简化此操作。