【问题标题】:How can I check if a list in a list comprehension inside a dictionary comprehension is empty?如何检查字典理解中的列表理解中的列表是否为空?
【发布时间】:2015-02-04 16:16:52
【问题描述】:

我目前在字典推导中使用列表推导来检测两个以列表为值的字典之间的变化。

代码如下所示:

detectedChanges = {table: [field for field in tableDict[table] if field not in fieldBlackList] for table in modifiedTableDict if table not in tableBlackList}

这将创建一个字典,其中每个条目都是表名,与之关联的是一个列表更改。

我遇到的问题是,尽管此代码有效,但生成的结构 detectedChanges 填充了仅包含表名和空列表的条目(意味着未检测到任何更改)。

我目前正在对字典进行后扫描,以便删除这些条目,但我想避免将它们放在字典中。

基本上,如果我能以某种方式对[field for field in tableDict[table] 进行长度检查或其他操作,我可以在创建 key:value 条目之前对其进行验证。

我现在使用的方法有没有办法做到这一点?

【问题讨论】:

  • 我不确定我是否理解你想要做什么;但是:您是否考虑过使用for 循环而不是字典理解?您的代码将更具可读性。
  • 哇...你明白了。老实说,我发现您的内容很难阅读,而您为删除特定字段而编写的任何内容只会使其更难阅读。就个人而言,我会将整个事情解开成一个循环,然后您的检查变得非常容易......
  • 我相信我理解你的理解和你的问题。我第三次@AndreaCorbellini 的建议是写出一个适当的for 循环。这样你就有了更多的权力,例如。使用continue 跳过添加空行。

标签: python list-comprehension dictionary-comprehension


【解决方案1】:

虽然 dict 推导很酷,但它们不应该被滥用。下面的代码不会太长,也可以放在窄屏上:

detectedChanges = {}
for table, fields in modifiedTableDict.iteritems():
    if table not in tableBlackList:
        good_fields = [field for field in fields
                             if field not in fieldBlackList]
        if good_fields:
            detectedChanges[table] = good_fields

【讨论】:

  • 我认为[field for field in fields if field not in fieldBlackList] 看起来你想要一个集合差异,即如果fieldsfieldBlackList 都是集合,那么你可以有good_fields = list(fields - fieldBlackList)
  • 是的,这似乎是一个更好的解决方案。但只是出于好奇,有没有办法在 1 行中实现我想要的?
  • @Duolasa。就在这里。我的回答有问题吗?
【解决方案2】:

只是对eumiro's answer 的补充。请先使用他们的答案,因为它更具可读性。但是,如果我没记错的话,理解通常更快,所以有一个用例,但 仅当这是您的代码中的一个瓶颈。这一点我怎么强调都不过分。

detectedChanges = {table: [field for field in tableDict[table]
                           if field not in fieldBlackList]
                   for table in modifiedTableDict
                   if table not in tableBlackList
                   if set(tableDict[table])-set(fieldBlackList)}

请注意这有多丑陋。我喜欢做这样的事情来更好地理解 Python,并且由于我以前遇到过这样的事情成为瓶颈。但是,在尝试解决可能不存在的问题之前,您应该始终use profiling

添加到您的代码[...] if set(tableDict[table])-set(fieldBlackList) [...] 会在当前表中创建一组条目,以及一组列入黑名单的字段,并获取当前表中但不在黑名单中的条目。空集评估为 False 导致理解忽略该表,就像它在 tableBlackList 变量中一样。为了更明确,可以将结果与一个空集进行比较,或者检查它是否有值。

另外,为了速度,更喜欢以下内容:

detectedChanges = {table: [field for field in fields
                           if field not in fieldBlackList]
                   for table, fields in modifiedTableDict.iteritems()
                   if table not in tableBlackList
                   if set(fields)-set(fieldBlackList)}

【讨论】:

  • 谢谢,就是这样。我试图在 1 行中做所有事情作为练习。我的代码实际上比我在此处发布的示例包含更多的 if 子句和理解,因此在 1 行中执行所有操作都会让人无法理解。使用像eumiro's answer中的格式将使代码更具可读性。尽管稍微慢了一点。
猜你喜欢
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 2015-08-21
  • 2018-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多