在列表推导中使用 break

2025-02-21 08:48:00
admin
原创
26
摘要:问题描述:如何根据某个条件(例如,当412找到数字时)中断列表理解?代码:numbers = [951, 402, 984, 651, 360, 69, 408, 319, 601, 485, 980, 507, 725, 547, 544, 615, 83, 165, 141, 501...

问题描述:

如何根据某个条件(例如,当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语句或类似的东西)


解决方案 1:

使用函数来引发StopIterationlist捕获它:

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

对于那些抱怨它是黑客行为并且不应该在生产代码中使用的人来说:嗯,你是对的。绝对如此。

解决方案 2:

您可以将生成器表达式与以下函数一起使用itertools.takewhile()

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

编辑:我刚刚注意到不要使用任何imports。好吧,无论如何我都会把这个答案留在这里。

解决方案 3:

我知道这是一个非常古老的帖子,但是因为 OP 询问了break在内部的使用list-comprehension,并且我也在寻找类似的东西,所以我想我会在这里发布我的发现以供将来参考。

在调查过程中break,我发现了一个鲜为人知的特性,iteriter(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.

这里比较棘手的部分是定义一个适合给定问题的函数。在这种情况下,首先我们需要将给定的转换listnumbers使用iteratorx = iter(numbers)并将其作为外部变量输入到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]

解决方案 4:

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

只需采用上述 FJ 的代码并添加三元组来检查 412 是否在列表中。仍然是“一行代码”,即使 412 不在列表中也能正常工作。

解决方案 5:

如果 412 肯定会在列表中,您可以使用以下命令:

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

如果您想在结果中包含 412,只需使用numbers[:numbers.index(412)+1]切片即可。

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

解决方案 6:

列表显示(包括列表推导)的语法在这里:http://docs.python.org/reference/expressions.html#list-displays

如您所见,没有特殊的whileuntil语法。最接近的语法是:

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

(代码取自 Sven Marnach 的回答,是我在输入这段内容时发布的)。

解决方案 7:

有一次我在网上遇到一个类似的问题,答案是:

next((x for x in [1, 2, 3, 4] if x % 2 == 0), [])

最后一个[]需要作为默认设置,以防止StopIteration找不到时出现错误

或者

any(print(x) if x < 2 else True for x in range(5))

print为了证明这一点,他又回来了None(合乎逻辑False)。

解决方案 8:

另一个巧妙的单行解决方案是在条件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 所说:

对于那些抱怨它是黑客行为并且不应该在生产代码中使用的人来说:嗯,你是对的。绝对如此。

解决方案 9:

考虑到生成器解决方案已经过时,我想出了以下解决方案:

even = [n for n in next((numbers[:i] for i, n in enumerate(numbers) if n == 412)) if not n % 2]

然后我回去看到了 Andrew Clark 的答案,虽然一样,但好多了

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]

解决方案 10:

我遇到了与破坏列表理解相同的问题。正如许多人所说,自 Python 3.5 以来,PEP 479的最高投票解决方案已经过时:StopIteration从生成器内部抛出的 将被转换为RuntimeError,而不是结束生成器本身。

我目前使用的是Python 3.11.4,其他所有解决方案(列表切片itertools.takewhile、短路any、断路器iterend@recnac 的东西)仍然有效。

我发现takewhile最优雅和最 Pythonic 的方法,但不知怎的,我想写一些该死的单行代码,实际上跳出列表而不是跳过列表的其余部分,但这似乎是无法实现的。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1519  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1345  
  信创软件在医疗行业中的创新应用信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控。随着数字化时代的发展,信创软件在各个行业的应用日益广泛,医疗行业也不例外。信创软件凭借其独特的优势,为医疗行业带来了诸多创新变革,从提升医疗服务质量到优化医疗管理流程,从保障医疗数据安全到推动医疗科研进步,都发挥着不可忽视的作用...
什么是信创产业   4  
  国产化信创的浪潮正席卷而来,对各行各业都产生了深远的影响。在这一宏大趋势下,中小企业也面临着新的机遇与挑战。信创产业,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,减少对国外技术的依赖。这一产业的发展不仅关乎国家的信息安全,也为中小企业的发展提供了诸多启示。深入探讨国产化信创对中小企业发展的启示,有助于中小企...
信创操作系统   4  
  随着信息技术的飞速发展,网络安全已经成为国家和企业发展过程中至关重要的一环。在数字化时代,信息的快速传播和广泛应用,使得网络安全面临着前所未有的挑战。国货国用信创的出现,为网络安全领域带来了新的机遇和解决方案。信创产业,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,从而保障国家信息安全。...
信创系统   4  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用