Py学习  »  Python

在python的[]中使用break或continue会产生错误[duplicate]

一笑奈何 • 4 年前 • 928 次点击  

我如何根据一个条件打破列表理解,例如 412 找到了吗?

代码:

numbers = [951, 402, 984, 651, 360, 69, 408, 319, 601, 485, 980, 507, 725, 547, 544,
           615, 83, 165, 141, 501, 263, 617, 865, 575, 219, 390, 984, 592, 236, 105, 942, 941,
           386, 462, 47, 418, 907, 344, 236, 375, 823, 566, 597, 978, 328, 615, 953, 345, 399,
           162, 758, 219, 918, 237, 412, 566, 826, 248, 866, 950, 626, 949, 687, 217, 815, 67,
           104, 58, 512, 24, 892, 894, 767, 553, 81, 379, 843, 831, 445, 742, 717, 958, 609, 842,
           451, 688, 753, 854, 685, 93, 857, 440, 380, 126, 721, 328, 753, 470, 743, 527]

even = [n for n in numbers if 0 == n % 2]

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

even = [n for n in numbers if 0 == n % 2 and break if n == 412]

真正地 首选:

  • 一行字
  • 如果可能的话,没有像itertools这样的高级库,“纯python”(阅读:解决方案不应该使用任何 import 声明或类似)
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/47039
 
928 次点击  
文章 [ 7 ]  |  最新文章 4 年前
recnac
Reply   •   1 楼
recnac    4 年前

另一个偷偷摸摸的单线解决方案 breaking in list comprehension ,借助于 end 条件。

不使用 numbers.index(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所说:

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

Marcin
Reply   •   2 楼
Marcin    12 年前

列表显示(包括列表理解)的语法如下: http://docs.python.org/reference/expressions.html#list-displays

如你所见,没有什么特别的 while until 语法。最接近的是:

even_numbers = (n for n in numbers if 0 == n % 2)
list(itertools.takewhile(lambda x: x != 412, even_numbers))

(代码取自sven marnach的答案,在我输入这个时发布)。

Anil_M
Reply   •   3 楼
Anil_M    6 年前

我知道这是一个很老的帖子,但是自从op问起 break 在一个 list-comprehension 我也在寻找类似的东西,我想我会把我的发现贴在这里,以备将来参考。

在调查的时候 打破 ,我偶然发现了 iter 作为 iter(callable, sentinel) 返回一个迭代器 “中断” 一次可调用的迭代 function 值等于 sentinel 价值。

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

这里棘手的部分是定义一个适合给定问题的函数。在这种情况下,首先我们需要转换给定的 list 属于 numbers 给一个 iterator 使用 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]
Andrew Clark
Reply   •   4 楼
Andrew Clark    12 年前

如果412肯定会在名单上,你可以用这个:

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

如果要在结果中包含412,请使用 numbers[:numbers.index(412)+1] 为了切片。

注意,由于切片的原因,这将比itertools或for循环解决方案效率低(至少在内存方面)。

Sven Marnach
Reply   •   5 楼
Sven Marnach    12 年前

可以将生成器表达式与 itertools.takewhile() 以下内容:

even_numbers = (n for n in numbers if not n % 2)
list(itertools.takewhile(lambda x: x != 412, even_numbers))

编辑 :我刚刚注意到不使用任何 import 好吧,我还是把这个答案留在这里。

WolframH
Reply   •   6 楼
WolframH    12 年前

使用函数来提升 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)

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

Michael David Watson
Reply   •   7 楼
Michael David Watson    8 年前
even = [n for n in numbers[:None if 412 not in numbers else numbers.index(412)] if not n % 2] 

只是取了上面F.J.的代码,添加了一个三值来检查412是否在列表中。仍然是一个'一行',将工作,即使412不在名单上。