2013-01-24 66 views
2

我有这个函数来检查我们在通过坐标系旅行时面对的方式,通过查看元组中的值如何增加或减少与路点列表中的下一个值相比较。看代码,它感觉复杂和笨拙:我如何缩短这个if语句?

a.facing = self.direction(a.travel_list[0], a.travel_list[1]) 

def direction(self, start, end): 
    s_width = start[0] 
    s_height = start[1] 
    e_width = end[0] 
    e_height = end[1] 
    # check directions 
    if s_height < e_height: 
     if s_width < e_width: 
      return 'right' 
     elif s_width > e_width: 
      return 'up' 
     else: 
      return 'up_right' 

    elif s_height > e_height: 
     if s_width < e_width: 
      return 'down' 
     elif s_width > e_width: 
      return 'left' 
     else: 
      return 'down_left' 

    elif s_height == e_height and s_width < e_width: 
     return 'down_right' 
    else: 
     return 'up_left' 

返回值被调整为顺时针旋转一步。我的问题是,我们如何更改代码以使功能更短,更高效?

编辑:请注意,只能在指定的8个方向上进行移动。

+0

“开始”和“结束”能够平等吗?你似乎没有正确处理这种情况。另外,我认为'elif s_height == e_height和s_width jimhark

+0

@jimhark我只在移动时调用这个函数,所以不需要改变面向方向。 –

+0

我刚刚注意到(通过测试)你制作的字符串,这个,非直观的。 @ AshRj的生成结果对我来说更有意义,但也许我不完全理解您的要求(或者可能是定义)。那么你能解释为什么'如果s_height jimhark

回答

5

使用()的基础上CMP字典返回值:

def direction(self, start, end): 
    return table[cmp(start[0], end[0]), cmp(start[1], end[1])] 

构建字典来概括当前的逻辑:

table = { 
    (-1, -1): 'right', 
    (-1, 1): 'up', 
    (-1, 0): 'up_right', 
     ... 
} 

如果你使用Python 3,您需要定义自己CMP()功能:

cmp = lambda x, y: -1 if x < y else 1 if x > y else 0 
1

步骤1:获取y和x的距离

步骤2:呼叫ATAN2(X,Y),以获得的角度(http://docs.python.org/2/library/math.html#math.atan2

步骤3:PI/4和圆形的鸿沟最近的整数以获得-4和4之间的值

第4步:现在您可以做一个case/switch,每个值都是不同的基本方向(例如-4和4将是相同的方向,例如两者东)

编辑:我刚刚意识到这一点如果你考虑如比东仍东高10度。 XD让我想到一个更好的...

编辑2:好了,试试这个:

步骤1:两个值

步骤2的元组:值1 = CMP(X1, X2)

步骤3:值2 = CMP(Y1,Y2)

步骤4:在元组方向的一个表执行查找(例如0,1是北,0,-1是南, 1,1是东北部等)并返回结果

+0

对不起,我应该提到,运动只是8路。我正在更新OP。 –

+0

这是我的错,我非常兴奋地使用atan2,我忘了它没有完成问题的定义。 LOL – Patashu

0

您可以使用and运营商:

a.facing = self.direction(a.travel_list[0], a.travel_list[1]) 

def direction(self, start, end): 
    s_width, s_height, e_width, e_height = start[0], start[1], end[0], end[1] 
    # multiple assignments 
    # check directions 
    if s_height < e_height and s_width < e_width: 
     return 'right' 
    elif s_height < e_height and s_width > e_width: 
     return 'up' 
    elif s_height < e_height: # this will get executed if the top two are false 
     return 'up_right'  # its similar to using the `else` in a nested conditional 
    elif s_height > e_height and s_width < e_width: 
     return 'down' 
    elif s_height > e_height and s_width > e_width: 
     return 'left' 
    elif s_height > e_height: 
     return 'down_left' 
    elif s_height == e_height and s_width < e_width: 
     return 'down_right' 
    else: 
     return 'up_left' 
2

在改变你的函数一点,你可以返回路线列表用一个简单的函数定义:

def direction(self, start, end): 
    delta = (end[0] - start[0], end[1] - start[1]) 

    s = [] 

    if delta[1]>0 : s.append("up") 
    elif delta[1]<0 : s.append("down") 

    if delta[0]>0 : s.append("right") 
    elif delta[0]<0 : s.append("left") 

    return s 

下面就包含为0,1或2名取决于方向旅行。在没有移动的情况下,该列表将是空的。

如果您特别需要指定格式的返回值,那么您可以简单地从列表中提取值并根据需要进行分析。


我不完全理解你的顺时针方向转变的需要,但如果那是不能改变的话,我会建议使用一些短/简单的值作为占位符开始,然后用字典来处理与占位符的两个替代所需的文字以及顺时针转换。

+0

您的映射'start'和'end'的逻辑是合理的,但与原始问题不符(这是没有道理的,但可能由于某种原因需要)。 – jimhark

+0

原始问题有:'s_width = start [0]; s_height =开始[1]; e_width = end [0]; e_height = end [1]'。所以[0]是x(宽度),[1]是高度。 (尽管目前尚不清楚其他代码是否与此一致。)您的轴是否已颠倒? – jimhark

+0

@jimhark是的,只要我关闭浏览器,我就意识到错误,但很忙,所以无法更改它。感谢您指出错误。 – asheeshr

0

如果你的原始代码是正确的,那么你的映射有些东西我不明白。假设起点是(宽度,高度),如你所说的那样,或者(x,y),正如我在下面所用的那样,假设x增加到右边,y增加(数学中通常的情况,但你的需求似乎是略有不同),这里有一个简洁的方式来告诉那里到底是相对于启动(使用字符串名称的设置):

DIR_STR_LIST = ("up", "down", "right", "left") 

def direction3((sx, sy), (ex, ey)): 
    conds = (sy < ey, ey < sy, sx < ex, ex < sx) 
    istr = DIR_STR_LIST.__iter__() 
    return '_'.join([istr.next() for c in conds if c or not istr.next()]) 

or not istr.next()推进迭代时c是假的需要。

虽然这简洁,它比我想要的有点丑陋。我认为它可能表现更好,然后原来的代码(因为列表解析是),但这是简单性更好的情况下。原始代码快5倍(哎!)。