Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在列表理解中使用break_Python_List Comprehension - Fatal编程技术网

Python 在列表理解中使用break

Python 在列表理解中使用break,python,list-comprehension,Python,List Comprehension,如何根据条件打破列表理解,例如当找到编号412时 代码: 所以从功能上来说,你可以推断这是应该做的: even = [n for n in numbers if 0 == n % 2 and break if n == 412] 我真的更喜欢: 一艘班轮 如果可能的话,没有其他像itertools这样的高级库,“纯python”(请阅读:解决方案不应使用任何import语句或类似语句) 如果412肯定会出现在列表中,您可以使用: even = [n for n in numbers[:num

如何根据条件打破列表理解,例如当找到编号
412

代码:

所以从功能上来说,你可以推断这是应该做的:

even = [n for n in numbers if 0 == n % 2 and break if n == 412]
我真的更喜欢:

  • 一艘班轮
  • 如果可能的话,没有其他像itertools这样的高级库,“纯python”(请阅读:解决方案不应使用任何
    import
    语句或类似语句)

如果412肯定会出现在列表中,您可以使用:

even = [n for n in numbers[:numbers.index(412)] if not n % 2]
如果要在结果中包含412,只需对切片使用
numbers[:numbers.index(412)+1]


请注意,由于切片的原因,这将比itertools或for循环解决方案的效率更低(至少在内存方面)。您可以将生成器表达式与itertools.takewhile()一起使用。


Edit:我刚刚注意到不使用任何
import
s的要求。好吧,我还是把这个答案留在这里。

使用一个函数来引发
StopIteration
list
来捕捉它:

>>> def end_of_loop():
...     raise StopIteration
... 
>>> even = list(end_of_loop() if n == 412 else n for n in numbers if 0 == n % 2)
>>> print(even)
[402, 984, 360, 408, 980, 544, 390, 984, 592, 236, 942, 386, 462, 418, 344, 236, 566, 978, 328, 162, 758, 918]
对于那些抱怨的人来说,这不是一句简单的话:

even = list(next(iter(())) if n == 412 else n for n in numbers if 0 == n % 2)

对于那些抱怨它是黑客的,不应该在生产代码中使用:嗯,你是对的肯定。

列表显示(包括列表理解)的语法如下:

如您所见,while或
直到
语法没有特殊的
。你能得到的最接近的是:

even_numbers = (n for n in numbers if 0 == n % 2)
list(itertools.takewhile(lambda x: x != 412, even_numbers))
(代码取自斯文·马纳奇的答案,在我打字时发布)


只是在上面取了F.J.的代码,并添加了一个三元组来检查412是否在列表中。仍然是“一行”,即使412不在列表中也会起作用。

我知道这是一篇非常古老的帖子,但是由于OP询问在
列表理解中使用
中断
,并且我也在寻找类似的东西,我想我会在这里发布我的发现以供将来参考

在研究
break
时,我发现
iter
的一个鲜为人知的特性是
iter(callable,sentinel)
,它返回一个迭代器,一旦可调用
函数
值等于
sentinel
值,它就会“break”迭代

>>> help(iter)
Help on built-in function iter in module __builtin__:

iter(...)
    iter(collection) -> iterator
    iter(callable, sentinel) -> iterator

    Get an iterator from an object.  In the first form, the argument must
    supply its own iterator, or be a sequence.
    In the second form, the callable is called until it returns the sentinel.
这里棘手的部分是定义一个适合给定问题的函数。在这种情况下,我们首先需要使用
x=iter(numbers)
将给定的
列表
中的
数字
转换为一个
迭代器
,该迭代器作为外部变量输入
lambda
函数

接下来,我们的可调用函数只是调用迭代器来输出下一个值。迭代器然后与我们的sentinel值(本例中为412)进行比较,并在达到该值后“中断”

print [i for i in iter(lambda x=iter(numbers): next(x),412) if i %2 == 0]

>>> 
[402, 984, 360, 408, 980, 544, 390, 984, 592, 236, 942, 386, 462, 418,  
 344, 236, 566, 978, 328, 162, 758, 918]

另一个利用
结束
条件解决
打断列表理解的狡猾的单行解决方案

如果不使用
数字。索引(412)
,可能会快一点

even = [n for end in [[]] for n in numbers
        if (False if end or n != 412 else end.append(42))
        or not end and not n % 2]

注意:这是个坏主意。只是为了好玩:) 正如@WolframH所说:

对于那些抱怨它是黑客的,不应该在生产代码中使用:嗯,你是对的肯定。


考虑到发电机解决方案已经过时,我提出了以下建议:

even = [n for n in next((numbers[:i] for i, n in enumerate(numbers) if n == 412)) if not n % 2]
然后我回去看了安德鲁·克拉克的答案,答案是一样的,但要好得多

even = [n for n in numbers[:numbers.index(412)] if not n % 2]
不管怎样,切片解决方案的最佳部分是,您可以选择在结束元素的任一侧包含或排除多个元素,例如,获取412和后面的数字:

even = [n for n in numbers[:numbers.index(412)+2] if not n % 2]


itertools
是纯python<代码>itertools
是Python。。。总的来说,这听起来像是一个普通的
for
循环的工作。@Flavius:为什么从Python自己的库中导入一些东西不“炫耀它的能力”?@Flavius:所以你试图说服你的同事,你可以用Python写一些粗俗难看的东西,这会给他们留下深刻印象?@Flavius,Python的强大之处在于它的标准库。如果内置更多的标准库函数,Python会“更强大”吗?我想不是。无论哪种方式,它们都是标准的,但如果它们是内置的,则命名空间冲突的可能性会更大。最好将它们分开。不仅因为切片效率较低,它还必须对列表进行线性搜索。@FelixKling-不过,在一次快速测试中,它与其他答案一起测试表明,对于提供的样本数据来说,这更快。不过,随着数据集的增加,我肯定会期望其他解决方案通过它。@FelixKling:412的线性搜索是超快速的C代码,而其他解决方案在Python代码中测试412,有些解决方案对每个数字都调用一个函数(在CPython中很昂贵)。我相信这个解决方案会更快列表复制也是用非常快的C代码完成的;除非内存紧张,否则不会出现性能问题。(好的,如果第一个数字是412,并且列表中有10**6个条目,这是不好的;但是如果412是最后一个数字,这个解决方案应该仍然非常非常快。)考虑到前面的评论,+1ed.有趣的技巧!并不是说我曾经在真实的代码中使用过它,但不管怎样,这是一个很好的观察结果。或者对于一行,用
end\u of_loop()
替换为
next(iter([])
@F.J是的,我在你发表评论前几分钟更新了我的答案。@Zuza一个非常类似的例子包含在政治公众人物部分中。你可以在最后找到它。单行解决方案将不再可行-您需要定义一个生成器函数。
RuntimeError:generator引发了StopIteration
如果他真的想要一行:
[itertools.takewhile(lambda x:x!=412,numbers)中的n代表n,如果不是n%2]
我没有投反对票,但我想这是因为你从别人那里拿走了密码。至少你承认了。如果412不在
numbers
中,如果是偶数,最后一个元素将丢失。谁是F.J.“上面的代码”在哪里?别搞错了
even = [n for n in next((numbers[:i] for i, n in enumerate(numbers) if n == 412)) if not n % 2]
even = [n for n in numbers[:numbers.index(412)] if not n % 2]
even = [n for n in numbers[:numbers.index(412)+2] if not n % 2]