首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python:带有2 for循环的Else语句

Python:带有2 for循环的Else语句
EN

Stack Overflow用户
提问于 2018-04-04 15:49:44
回答 4查看 698关注 0票数 3

我正在寻找节奏曲的方法来做以下事情:

我有一个键列表和一个对象列表。

对于任何键,都应该使用与该键相匹配的第一个对象来完成一些操作。

如果没有任何对象适合于任何键,所以根本没有做任何事情,那么就应该做一些不同的事情。

我按照以下方式实现了这一点,它正在正常工作:

代码语言:javascript
复制
didSomething = False
for key in keys:
    for obj in objects:
        if <obj fits to key>:
            doSomething(obj, key)
            didSomething = True
            break
if not didSomething:
    doSomethingDifferent()

但是,通常情况下,如果只有一个换循环,则不需要这样一个临时布尔值来检查是否已经做了一些事情。您可以使用for-else语句代替。但这不适用于2个for-循环,对吗?

我觉得应该有更好的方法来做这件事,但我不明白。你有什么想法吗?还是没有改进?

谢谢您:)

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-04-04 15:57:54

这并不真正符合for/else范式,因为您不想破坏外部循环。因此,只需使用一个变量来跟踪是否做了一些事情,就像在您的原始代码中一样。

不要使用第二个循环,而是使用一个找到第一个匹配对象的表达式。有关此操作的方法,请参阅Python: Find in list

代码语言:javascript
复制
didSomething = false
for key in keys:
    found = next((obj for obj in objects if <obj fits to key>), None)
    if found:
        doSomething(found, key)
        didSomething = true
if not didSomething:
    doSomethingDifferent()
票数 3
EN

Stack Overflow用户

发布于 2018-04-04 16:20:58

每当您发现自己需要跳出嵌套循环时,通常很难仔细考虑细节,当您计算完它时,答案通常是不可能的(或者,至少只有使用显式标志变量、异常或其他模糊逻辑的东西才有可能)。

对此有一个简单的答案(我将在下面列出,以防通过搜索发现这个问题的人有这个问题),但这其实不是你的问题。您要检查的不是“我是否正常完成循环”,因为您总是正常地完成循环。您要检查的是“我做了什么事情(在本例中称为doSomething)一次或多次吗?”

这并不是关于外部循环的,不像打破外部循环(显然是这样),所以它没有语法。你需要跟踪你是做了一次还是多次,而你已经在做的方式可能是最简单的方式。

在某些情况下,您可以重新排列东西以使循环变平或反转,所以您最终会对所有当前的外部值做一件事情--一次并突破该循环,在这种情况下,它是关于循环的。但是如果这会扭曲你的逻辑,以至于它不再清楚是怎么回事,那就不会是一个改进。例如:

代码语言:javascript
复制
fits = set()
for key in keys:
    for obj in objects:
        if <obj fits to key>:
            fits.add((obj, key))
for obj, key in fits:
    do_something(obj, key)
if not fits:
    do_something_else()

这可以简化如下:

代码语言:javascript
复制
fits = {(obj, key) for key in keys for obj in objects if <obj fits to key>}
for obj, key in fits:
    do_something(obj, key)
if not fits:
    do_something_else()

但是,无论哪种方式,请注意,我避免存储一个标志的方式,您是否曾经找到合适的是存储一组您找到的所有适合。对于一些问题,这是一个改进。但如果那套可能很大,那是个糟糕的主意。如果这个集合在概念上并不意味着你的问题中的任何东西,它可能会模糊逻辑而不是简化它。

如果您的问题脱离了一个嵌套循环(但它不是,但也可能是其他通过搜索找到这个问题的人),那么总是有一个简单的答案:只需将整个循环集合重构成一个函数即可。然后,只要使用return,就可以在任何级别上爆发出来。如果您没有在任何地方return,循环后的代码将被运行,而如果您执行return,它将运行-就像一个else

所以:

代码语言:javascript
复制
def fits():
    for key in keys:
        for obj in objects:
            if <obj fits to key>:
                doSomething(obj, key)
                return
    doSomethingDifferent()

fits()

我不确定如果这两个循环都是你想要的。如果是的话,这正是你想要的。如果不是,它不会,但我不知道您在运行else-when时要寻找什么语义,所以我不知道如何解释如何做到这一点。

一旦您这样做了,您可能会发现抽象在代码中的泛化程度超过了使用范围,因此您可以将函数转换为接受参数而不是使用闭包或全局变量,并且返回值或引发而不是调用两个函数之一的函数,等等。但有时,这个微不足道的局部函数就是您所需要的。

票数 3
EN

Stack Overflow用户

发布于 2018-04-04 16:07:38

没有真正的方法来简化代码。然而,它的写作方式有点混乱。实际上,我会让它更详细,以确保它的正确阅读:

代码语言:javascript
复制
def fit_objects_to_keys(objects, keys):
    for key in keys:
        for obj in objects:
            if <obj fits to key>:
                yield obj, key
                break

none_fit = True

for obj, key in fit_objects_to_keys(keys, objects):
    doSomething(obj, key)
    none_fit = False

if none_fit:
    doSomethingDifferent()

如果您解释<obj fits to key>的实际操作,您可能可以进一步简化它。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49655375

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档