如何简化python中的重复列表理解?

如何简化python中的重复列表理解?,python,syntax,refactoring,list-comprehension,Python,Syntax,Refactoring,List Comprehension,此代码计算包含输入矩形列表的最小矩形: left = min(x.left for x in rect) bottom = min(x.bottom for x in rect) right = max(x.right for x in rect) top = max(x.top for x in rect) 我相信这可以简化为单行语句,但老实说,我不知道怎么做。任何帮助都将不胜感激。此处不要使用生成器表达式,只需循环一次,一次性更新minimi和maximi: left = bottom =

此代码计算包含输入矩形列表的最小矩形:

left = min(x.left for x in rect)
bottom = min(x.bottom for x in rect)
right = max(x.right for x in rect)
top = max(x.top for x in rect)

我相信这可以简化为单行语句,但老实说,我不知道怎么做。任何帮助都将不胜感激。

此处不要使用生成器表达式,只需循环一次,一次性更新minimi和maximi:

left = bottom = float('inf')
right = top = float('-inf')
for x in rect:
    if x.left < left:     left = x.left
    if x.bottom < bottom: bottom = x.bottom
    if x.right > right:   right = x.right
    if x.top > top:       top = x.top

但这几乎不值得抽象,不是每个值都有两个值。

您可以通过减少来解决问题,但它可能比Martijn Pieters的建议效率低

from functools import reduce

def fn(current_mins_maxs, r):
    z = zip(current_mins_maxs, (r.left, r.bottom, r.right, r.top))
    return [min(z[0]), min(z[1]), max(z[2]), max(z[3])]

first, rest = rectangles[0], rectangles[1:]
# Or, if you are using Python 3, you can write:
# first, *rest = rectangles
mins_and_maxs = reduce(fn, rest, (first.left, first.bottom, first.right, first.top))    

我更喜欢:
left=min(left,x.left)
等。避免所有
如果
s。。。当然,你需要支付4次函数调用的费用,这可能会很昂贵,但我觉得它更具可读性。@Bakuriu:这意味着你要调用一个函数,每个循环分配4次。只是测试会更快。OP是在嵌套的
for
循环中执行此操作的,使差异更加复杂。好的,我认为可以有一个列表理解,相当于一个循环,但更简洁…@mnowotka:不,列表理解总是产生一个列表。您可以使用
zip()
将行拆分为列,但最终仍然会有4个循环来确定单独的最小值和最大值。@mnowotka,您的意思是在一个理解中创建4个列表。。。好了,没有这样的事情。注意,你根本不需要列表的理解。您可以只使用genexps:
min(x.left表示矩形中的x)
。这样可以避免创建列表对象。@Bakuriu-是的,这样做更好(已更正),但仍然不够干爽。我只是想指出,使用列表理解法是在浪费空间。然而,我仍然不清楚您是否关心该循环的性能,或者您只是想避免代码重复。@Martijn:reduce只遍历列表一次,OP的代码遍历列表四次。啊,不,我误解了您的
矩形
列表是什么。这与编辑文章中的
rect
列表相同。
from functools import reduce

def fn(current_mins_maxs, r):
    z = zip(current_mins_maxs, (r.left, r.bottom, r.right, r.top))
    return [min(z[0]), min(z[1]), max(z[2]), max(z[3])]

first, rest = rectangles[0], rectangles[1:]
# Or, if you are using Python 3, you can write:
# first, *rest = rectangles
mins_and_maxs = reduce(fn, rest, (first.left, first.bottom, first.right, first.top))