【问题标题】:Stop loop with list comprehension when find the first True找到第一个 True 时使用列表理解停止循环
【发布时间】:2019-11-10 03:27:24
【问题描述】:

我想在找到第一个 True 时停止迭代,如下所示:

>> for x in ['a', 'b', 1, 2, 3]:
>>    if isinstance(x, int):
>>        print(x)
>>        break

 1

除了 列表理解 for-loop,我如何做同样的事情?

【问题讨论】:

  • break list comprehension的可能重复
  • 虽然这是可能的,但它远不如循环美观。
  • list comprehension 是一种创建list 的简洁方法,在找到之前不搜索某物,然后将其打印出来——这就是您的代码正在做的事情。请更具体地说明您想要什么。

标签: python for-loop list-comprehension break


【解决方案1】:

您可以在生成器表达式上使用next 来返回第一个True 实例:

x = next((a for a in ['a', 'b', 1, 2, 3] if isinstance(a, int)), None)
print(x)
1

x = next((a for a in ['a', 'b'] if isinstance(a, int)), None)
print(x)
None

第二个参数是一个返回值,可以避免StopIteration 错误

编辑(信用@martineau)

这可以简化为 filter 运算符,如上面的 itertools 配方所示:

x = next(filter(int.__instancecheck__, ['a', 'b', 1, 2, 3]), None)

【讨论】:

  • 你的代码可以被缩短,因为它的很大一部分相当于内置的 filter() 函数所做的——这可能就是为什么 itertools recipe 命名为 first_true() 使用它.
  • 没错,next(filter(...)) 在这里可能会更快
【解决方案2】:

不幸的是,没有用于查找列表中与谓词匹配的第一个元素的内置机制。有any,你可以用它来确定if这样的元素是否存在,但这不会告诉你它是什么元素。

any(isinstance(x, int) for x in ['a', 'b', 1, 2, 3])

幸运的是,itertools 提供了多种功能,供您在列表或任何其他可迭代对象上执行某些操作时使用。

您要查找的函数未内置到模块中,但文档提供了一些函数的定义,包括这个函数,如 itertools recipes。您需要的函数名为first_true。只需复制定义,然后:

def first_true(iterabe, default=False, pred=None):
    return next(filter(pred, iterable), default)

x = first_true(['a', 'b', 1, 2, 3], pred=int.__instancecheck__)

如果列表中没有任何内容与谓词匹配,first_true 将返回 False。如果您想要不同的行为,您可以修改该功能。如果您想了解如何在 itertools 样式中使用迭代器,其他秘籍可能是一个不错的起点。


如果您尝试在循环中进行比仅查找第一个匹配元素更复杂的处理,那么您最好使用正确的for 循环。列表推导式和生成器表达式可以很好地替代 map 和 filter,并且 itertools 提供了对可迭代对象的更通用操作,但它们并不代表真正的循环逻辑。

【讨论】:

  • 我收到NameError: name 'first_true' is not defined
  • 您需要定义first_true函数,使用链接列表中的定义。为此,您需要从 itertools 导入一些函数。 (我会在此处包含定义,但我不拥有它的版权。)
  • @jirassimok:Python 是开源的,所以不要担心从中复制代码,尤其是从它的文档示例中复制代码(只要你像现在一样引用源代码)。
  • @martineau 我知道;它应该属于合理使用范围。实际上,我不确定我在写这篇文章时还在想什么。
  • 虽然根据itertools配方定义一个函数会更优雅和可读,但它太短了,可以简单地使用它——即x = next(filter(int.__instancecheck__, ['a', 'b', 1, 2, 3]), None)
猜你喜欢
  • 2019-10-17
  • 2023-03-28
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多