2011-11-05 47 views
3

我很努力地理解下面用python写的'reduce'调用。Python to c#reduce函数理解

我在这里和其他地方发现了几个来源,说明函数做了什么,并且在C#中有一个等效的“聚合”列表,但我无法理解下面的调用实际上是什么-expect- ...可能是因为我无法确定'_keep_left'返回的是什么?

所以:

1 - 任何人可以帮助告诉我什么是 '_keep_left' 回来?

2-什么是, [])在减少电话中的含义?

非常感谢。

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 

回答

3
  1. _keep_left返回一个列表hull,其最初是空的。不会向左移动。当前点被添加到它,除非它已经是列表中的最后一个元素。

  2. , [])是要减少的第三个参数。这是初始累加器值,它将被传递到_keep_left,从而使hull(最后是lhuh)最初为空。

它通过第一分选点,然后通过所有点持续两次(lhuh立场下半部和上半部),以及与每个扫点被累积到列表执行Graham scan。点数与reduce累计,即结果原来为空,点数依次传递给_keep_left(按排序顺序),对于每个点,右转的点从累计列表中删除。然后将当前点添加到累积列表中。

_keep_left的返回值有点棘手:not len(hull)如果列表为空,则返回True。 hull[-1] != r检查r(当前点)是否是列表中的最后一个元素。 hull.append(r)仅在为列表追加r(对我而言看起来有点脏)的副作用中为布尔表达式,所以如果hull的最后一个元素是r,hull将不返回r而返回给它。换句话说,由于短路,hull将始终返回,但r将被追加到它之前返回它,如果它不是最后一个元素。同样的逻辑应该很容易以更好,更详细的方式实现。

+0

感谢您的非常明确的解释。我被'减少'会返回一些有意义的迭代的期望所欺骗,而真正的行动发生在turn_left中的'append'命令!哈! – roamcel