0

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

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()]  

但我认为你不能有“=”

4

5 回答 5

2

您不能使用 dict 理解向 dict 添加项目;dict理解创建一个与先前存在的dict分开的新dict,如果你想将新旧结合起来,你必须明确地这样做,例如:

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

(请注意,y not in x.keys()在处理 dicts 时这是不必要的,因为您可以这样做y not in x。)

如果您一心想摆脱该 outer for,则方法是创建一个新字典的新列表:

list_of_dicts2 = [dict(x, **{y: '' for y in header if y not in x}) for x in list_of_dicts]
于 2013-12-11T02:14:26.330 回答
2

这不是您应该通过列表理解来解决的问题。您可以使用一些集合操作改进现有代码:

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

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

这利用字典视图对象为我们提供字典键的类似集合的视图;在 Python 3 中,这种行为现在是默认行为。

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

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

使用集合操作使代码更具可读性和效率,推动任何循环以确定集合差异到优化的 C 例程中。

于 2013-12-11T02:17:14.937 回答
1

有很多方法可以更好地做到这一点。主要是通过更好地思考你正在尝试做的事情。

你想做什么?你可以这样想:你想为一些字典添加默认值。dict.setdefault()马上想到方法:

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

您可以稍微换一种方式思考:我需要将一组默认值应用于所有 dicts。现在先构建defaultsdict 然后合并它感觉很自然:

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

请注意,我们在这里重建每个字典而不是更新它。这是使用推导式的正确方法。这里要补充的一件事是,将最后一行与代码构造合并list_of_dicts可能是有意义的(我不能在没有看到的情况下肯定地说)。

于 2013-12-11T02:30:53.697 回答
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))

尽管如此,关于使用生成器的副作用的某种警告可能应该适用。

于 2013-12-11T02:24:01.507 回答
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}
>>> 
于 2013-12-11T02:38:44.690 回答