2013-01-24 89 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倍(哎!)。