Python转C#:理解reduce函数

3
我很难理解下面Python中的'reduce'调用。我已经找到了几个来源,无论是这里还是其他地方,都说明该函数的作用,并且在C#中有一个等效的“聚合”列表,但我无法理解下面的调用实际上期望什么...可能是因为我无法真正弄清楚'_keep_left'返回什么?
所以:
1- 有人可以帮助告诉我'_keep_left'返回什么吗?
2- 在reduce调用中,,[]表示什么意思?
非常感谢。
TURN_LEFT, TURN_RIGHT, TURN_NONE = (1, -1, 0)

def turn(p, q, r):
    """Returns -1, 0, 1 if p,q,r forms a right, straight, or left turn."""
    return cmp((q[0] - p[0])*(r[1] - p[1]) - (r[0] - p[0])*(q[1] - p[1]), 0)

def _keep_left(hull, r):
    while len(hull) > 1 and turn(hull[-2], hull[-1], r) != TURN_LEFT:
            hull.pop()
    return (not len(hull) or hull[-1] != r) and hull.append(r) or hull

def _graham_scan(points):
    """Returns points on convex hull of an array of points in CCW order."""
    points.sort()
    lh = reduce(_keep_left, points, [])
    uh = reduce(_keep_left, reversed(points), [])
    return lh.extend(uh[i] for i in xrange(1, len(uh) - 1)) or lh
1个回答

3
  1. _keep_left返回一个名为hull的列表,初始为空。将不向左转的点从中删除。除非当前点已经是列表中的最后一个元素,否则将其添加到其中。

  2. , [])是reduce的第三个参数。它是初始累加器值,将被传递给_keep_left,从而使hull(以及最终的lhuh)最初为空。

它通过首先对点进行排序,然后两次遍历所有点(lhuh代表下半部分和上半部分),执行Graham扫描。每次扫描都会将点累积到列表中。使用reduce累积点,即结果最初为空,并且按照排序顺序逐个将点传递给_keep_left,对于每个点,从累积列表中删除导致右转的点。然后将当前点添加到累积列表中。

_keep_left的返回值有点棘手:not len(hull)如果列表为空,则返回True。hull[-1] != r检查r(当前点)是否是列表中的最后一个元素。hull.append(r)仅用于将r附加到列表中的副作用(对我来说看起来有点不干净),因此如果hull的最后一个元素是r,则将返回hull而无需将r附加到其中。

换句话说,由于短路,hull将始终被返回,但是如果它不是最后一个元素,则在返回它之前将r附加到其中。可以以更好、更冗长的方式实现相同的逻辑。


感谢您提供如此清晰明了的解释。我被期望“reduce”在迭代中返回有意义的内容所欺骗,而真正的操作是由“append”命令在turn_left中发生的!哈哈! - roamcel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接