找到第一个 True 时停止使用列表理解循环

Stop loop with list comprehension when find the first True

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

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

 1

除了使用 list comprehension for-loop,我怎样才能做同样的事情?

遗憾的是,没有用于查找与谓词匹配的列表的第一个元素的内置机制。有 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 将 return False。如果你想要不同的行为,你可以修改函数。如果你想了解如何使用 itertools 风格的迭代器,其他食谱可能是一个很好的起点。


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

您可以在生成器表达式上使用 next 来 return 第一个 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

其中第二个参数是一个 return 值,可以避免 StopIteration 错误

编辑(信用@martineau)

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

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