【问题标题】:Trying to convert python nested for loops to list/dict comprehension试图将python嵌套的for循环转换为list/dict理解
【发布时间】:2013-12-28 20:12:42
【问题描述】:

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

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

它需要一个字典列表并添加 key:value 对,默认值 = '' for any
当前字典中尚不存在的键。

我还是 python 的新手,所以任何帮助都将不胜感激。我试过了:

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

但我认为你不能有“=”

【问题讨论】:

  • 推导是为了建立一个列表,而不是为了执行一系列赋值语句。
  • 也许考虑将list_of_dicts 改为defaultdict 列表,这样您就不必为未定义的键显式填充它?
  • if y not in x.keys() - 放弃keys() 电话。在 Python 2 上,这将构建一个不必要的键列表,然后遍历它们以找到 y,完全放弃了使用 dict 的好处。在 Python 3 上,这只是不必要的输入。 if y not in x 是你想要的。
  • 此外,dicts 有一个 setdefault 方法,如果键不存在,它将为键设置默认值,所以如果你愿意,你可以使用 x.setdefault(y, '') 并删除 @987654331 @.

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


【解决方案1】:

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

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

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

【讨论】:

  • header 实际上可能不是字典。
  • @user2357112:确实;我可能误读了这个问题;我推断并且可能推断错了。
  • 为每个x 创建一个集合的额外工作是否实际上使集合差异比not in 测试更有效或更差,大概是相当复杂的。大概取决于它的大小吧?还是在 Python 中对 header 进行迭代与在 C 中进行迭代相比慢得多,以至于没有多少内存分配会更慢?
  • 设置设置是一次性成本,在list_of_dicts 的几次迭代中轻松赢回。但是,我现在无法运行timeit 试验。是的,建立差异的 C 循环将比字节码驱动循环快很多。
  • @MartijnPieters:我的意思是由set.difference() 构造的集合,其中有len(list_of_dicts) 调用不只是一个。
【解决方案2】:

您不能使用字典推导向字典添加项目; 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。)

如果你一心想摆脱那个外部的for,方法是创建一个新的新字典列表:

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

【讨论】:

  • 很好地使用 dict() 关键字参数来“更新”列表理解中的新字典!
  • 如果键不都是字符串,则第二个示例在 Python 3 中不起作用。
  • 谢谢jwodder!感谢您的帮助。
  • @jwodder 见上文赞赏^
【解决方案3】:

有很多方法可以让您做得更好。主要是通过更好地思考你正在尝试做的事情。

你想做什么?你可以这样想:你想为一些字典添加默认值。 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]

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

【讨论】:

  • 列表解析确实假定d 中的所有键都是字符串,但defaults 设置是一个不错的方法!
  • 不,不是。在 python 控制台中试试这个dict({}, **{None: 1})
  • 现在在 Python 3 中尝试一下 :-)
【解决方案4】:

可以为此使用列表推导,但您不应该:

[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))

不过,关于使用生成器的副作用的某种警告可能应该适用。

【讨论】:

  • 这不是Nones 的大列表,因为setdefault 返回键的值,但它是一个不必要的大列表。
【解决方案5】:
>>> 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}
>>> 

【讨论】:

    猜你喜欢
    • 2021-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-21
    • 1970-01-01
    • 2021-02-03
    • 2021-12-30
    • 2021-09-02
    相关资源
    最近更新 更多