打破清单理解
我怎样才能打破基于条件的列表理解,例如,当find412
号?
码:
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]
所以在function上,这是你可以推断这是应该做的事情:
even = [n for n in numbers if 0 == n % 2 and break if n == 412]
我真的更喜欢:
- 一个class轮
- 没有像itertools的其他花式库,如果可能的话,“纯Python”(阅读:解决scheme不应该使用任何
import
声明或类似的)
even = [n for n in numbers[:None if 412 not in numbers else numbers.index(412)] if not n % 2]
刚刚拿了上面的FJ的代码,并添加了一个三元组来检查412是否在列表中。 仍然是一个“class轮”,即使412不在列表中,也将起作用。
使用函数来提高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)
对于那些抱怨它是骇人听闻,不应该在生产代码中使用:那么,你是对的。 当然。
你可以和itertools.takewhile()
一起使用生成器expression式:
even_numbers = (n for n in numbers if not n % 2) list(itertools.takewhile(lambda x: x != 412, even_numbers))
编辑 :我只是注意到要求不使用任何import
。 好吧,我在这里留下这个答案。
如果412肯定会在列表中,你可以使用这个:
even = [n for n in numbers[:numbers.index(412)] if not n % 2]
如果要在结果中包含412,则只需使用numbers[:numbers.index(412)+1]
作为切片。
请注意,由于切片,这将比itertools或for循环解决scheme效率更低(至less在内存方面)。
列表显示(包括列表parsing)的语法如下: 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的答案,当我打字的时候张贴)。
我知道这是一个非常古老的post,但是因为OP询问在list-comprehension
使用break
而且我也在寻找类似的东西,所以我想我会在此发布我的发现以备将来参考。
在调查break
,我发现iter
小特性就是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.
这里的棘手的部分是定义一个函数,将适合给定的问题。 在这种情况下,首先我们需要使用x = iter(numbers)
将给定的numbers
list
转换为一个iterator
,它将外部variables作为lambda
函数提供。
接下来,我们的可调用函数只是一个调用迭代器吐出下一个值。 迭代器然后与我们的标记值(在这种情况下为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]