试图将python嵌套for循环转换为list / dict理解

时间:2013-12-11 02:08:48

标签: python for-loop nested list-comprehension dictionary-comprehension

我正在尝试将以下代码转换为更具可读性的代码。

for x in list_of_dicts:
    for y in header:
        if y not in x.keys():
            x[y] = ''

它需要一个字典列表,并为任何
添加键值:值对,默认值为“'” 当前字典中尚不存在的键。

我还是python的新手,所以任何帮助都会非常感激。我试过了:

return [x[y] = '' for x in list_of_dicts for y in header if y not in x.keys()]  

但我认为你不能拥有“=”

5 个答案:

答案 0 :(得分:2)

你不能使用dict理解来向dict添加项目; dict comprehension创建一个与已有的dict分开的新dict,如果你想要结合新旧,你必须明确地这样做,例如:

for x in list_of_dicts:
    x.update({y: '' for y in header if y not in x})

(注意在处理dicts时不需要y not in x.keys(),因为你可以y not in x。)

如果您在摆脱外部for时已经死定,那么这样做的方法是创建一个新的新词典列表:

list_of_dicts2 = [dict(x, **{y: '' for y in header if y not in x}) for x in list_of_dicts]

答案 1 :(得分:2)

这不是你应该用列表理解解决的问题。您可以使用某些设置操作 改进现有代码:

for x in list_of_dicts:
    x.update((y, '') for y in header.viewkeys() - x)

这将达到同样的效果;将header中缺少的键添加为空字符串。对于Python 3,将viewkeys()替换为keys()

这使用dictionary view objects为字典键提供了类似于集合的视图;在Python 3中,此行为现在是默认行为。

如果我错误地阅读了你的问题并且headers也不是字典,那么请将其设为明确的集合以获得相同的好处:

header_set = set(header)
for x in list_of_dicts:
    x.update((y, '') for y in header_set.difference(x))

使用set操作使代码更具可读性和效率,推送任何循环以确定优化C例程的设置差异。

答案 2 :(得分:1)

可以使用列表理解,但你不应该:

[x.setdefault(y, '') for x in list_of_dicts for y in header]

你不应该这样做的原因是这会创建一个你不需要但需要时间和记忆的大旧列表。

您可以在不创建大的旧列表的情况下使用生成器理解:

import collections
def consume(iterator):
    collections.deque(iterator, maxlen = 0)

consume(x.setdefault(y, '') for x in list_of_dicts for y in header)

可以说你不应该这样做,因为读者并没有真正期望理解产生副作用,所以代码可能会吓到并混淆它们。

你是正确的,你不能在理解中做x[y] = '',因为它是一个陈述而不是一个表达。恰好x.setdefault(y, '')做了你想做的事,但是如果没有这样方便的功能那么你可以写一个。并且想一想,通过这样做,你可以消除理解以及原始循环:

def set_default(x, y):
    if y not in x:
        x[y] = ''

consume(itertools.starmap(set_default, itertools.product(list_of_dicts, header))

同样,有关使用发生器产生副作用的某种警告应该适用。

答案 3 :(得分:1)

有很多方法可以做得更好。通过更好地思考你想要做的事情来学习。

你想做什么?您可以这样想:您想要为某些dicts添加默认值。我立刻想到了dict.setdefault()方法:

for d in list_of_dicts:
    for h in header:
        d.setdefault(h, '')

您可以稍微考虑其他方式:我需要将一组默认值应用于所有dicts。现在首先构建defaults dict然后合并它感觉很自然:

defaults = dict.fromkeys(header, '')
list_of_dicts = [dict(defaults, **d) for d in list_of_dicts]

请注意,我们正在重建每个dict,而不是更新它。这是使用理解时的正确方法。这里要补充的一点是,将最后一行与构造list_of_dicts的代码合并可能是有意义的(我不能肯定地说没有看到)。

答案 4 :(得分:0)

>>> d1={'a':1}
>>> d2={'b':2}
>>> d3={'c':3}
>>> listofdict=[d1, d2, d3]
>>> listofdict
[{'a': 1}, {'b': 2}, {'c': 3}]
>>> header = ['x', 'y']
>>> header
['x', 'y']
>>> [ x.update({k:''}) for x in listofdict for k in header if not x.get(k) ]
[None, None, None, None, None, None]
>>> listofdict
[{'a': 1, 'x': '', 'y': ''}, {'y': '', 'x': '', 'b': 2}, {'y': '', 'x': '', 'c': 3}]
>>> d1
{'a': 1, 'x': '', 'y': ''}
>>> d2
{'y': '', 'x': '', 'b': 2}
>>> d3
{'y': '', 'x': '', 'c': 3}
>>>