2013-03-20 121 views
3

我有一個遍歷樹並將元素作爲列表返回的函數。有沒有辦法簡化treeToList::traverse中的所有if語句,因爲它看起來有點多餘?Python:簡化很多if語句

#!/usr/bin/python 

def enum(**enums): 
    return type('Enum',(), enums) 

Order = enum(PREORDER=0, INORDER=1, POSTORDER=2) 
def treeToList(root, order=Order.INORDER): 
    ret = list() 
    def traverse(node, order): 
    if order == Order.PREORDER: ret.append(node.data) 
    if node.right != None: traverse(node.right, order) 
    if order == Order.INORDER: ret.append(node.data) 
    if node.down != None: traverse(node.down, order) 
    if order == Order.POSTORDER: ret.append(node.data) 
    traverse(root, order) 
    return ret 

class node: 
    def __init__(self, data=None): 
    self.data = data 
    self.down = None 
    self.right = None 

if __name__ == '__main__': 
    root = node('F') 
    root.right = node('B') 
    root.down = node('G') 
    root.right.right = node('A') 
    root.right.down = node('D') 
    root.down.down = node('I') 
    root.right.down.right = node('C') 
    root.right.down.down = node('E') 
    root.down.down.right = node('H') 

    print treeToList(root, Order.PREORDER) 
    print treeToList(root, Order.INORDER) 
    print treeToList(root, Order.POSTORDER) 

輸出

['F', 'B', 'A', 'D', 'C', 'E', 'G', 'I', 'H'] 
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'] 
['A', 'C', 'E', 'D', 'B', 'H', 'I', 'G', 'F'] 
+0

簡短回答:否:) – isedev 2013-03-20 23:53:38

+1

+1包括一個帶重構請求的測試套件:) – 2013-03-21 00:05:12

回答

5

好吧,如果你擺脫封閉的..純函數可能更清楚:

def treeToList(node, order=Order.INORDER): 
    if node is None: 
     return [] 

    right = treeToList(node.right, order) 
    down = treeToList(node.down, order) 
    current = [node.data] 

    if order == Order.PREORDER: 
     return current + right + down 

    if order == Order.INORDER: 
     return right + current + down 

    if order == Order.POSTORDER: 
     return right + down + current 

而是建立一個很多中間名單當然。

+0

+1。這正是我最後一段的意思。我認爲使用Python編寫比使用英文更容易。 (這樣理解肯定更容易。) – abarnert 2013-03-21 00:02:13

0

試着這麼做

if order in (Order.PREORDER, Order.INORDER, ...): 
    ret.append(node.data) 

挑剔

你應該在多行

if cond: 
    pass 

,而不是

if cond: pass 

你的條件也考慮比較None,而不是==!=在使用isis not

+1

與之前(現在刪除)相同的問題答案:條件的順序非常重要...您建議的訂單更改。 – isedev 2013-03-20 23:53:12

+0

@isedev,+1你是對的,我會離開它,讓別人不會犯同樣的錯誤。 – John 2013-03-20 23:57:06

+0

夠公平,不能刪除-1(不是我)。 – isedev 2013-03-20 23:58:11

2

是在我腦海中的唯一事情是這樣的:

def treeToList(root, order=Order.INORDER): 
    ret = list() 
    def inorder_traversal(node): 
     if node is not None: 
      inorder_traversal(node.right) 
      ret.append(node.data) 
      inorder_traversal(node.down) 

    def preorder_traversal(node): 
     if node is not None: 
      ret.append(node.data) 
      preorder_traversal(node.right) 
      preorder_traversal(node.down) 

    def postorder_traversal(node): 
     if node is not None: 
      postorder_traversal(node.right) 
      postorder_traversal(node.down) 
      ret.append(node.data) 

    if order == Order.PREORDER: 
     preorder_traversal(node) 
    elif order == Order.INORDER: 
     inorder_traversal(node) 
    else: 
     postorder_traversal(node) 

    return ret 
+0

儘管...並不是一個簡單的方式,但是更方便,所以+1。 – isedev 2013-03-20 23:54:22

+0

我認爲更清楚的是每個遍歷在這裏都比在原始問題中正確實現。但是,沒有太多可以做的澄清這個代碼。 – 2013-03-20 23:55:15

+0

如果你真的想:'(preorder_traversal,inorder_traversal,postorder_traversal)[order](node)'實際上會使這個「更簡單」......但顯然不太可讀。 – abarnert 2013-03-21 00:03:15

2

我不認爲有一種好的方法可以在不重新組織算法的情況下消除三個if order語句。 ret.append發生的位置取決於數值,所以您幾乎必須以這種或那種方式檢查三次。

但是有重組的事情,除去一對夫婦if■一個明顯的方式:

def traverse(node, order): 
    if node is None: return 
    if order == Order.PREORDER: ret.append(node.data) 
    traverse(node.right, order) 
    if order == Order.INORDER: ret.append(node.data) 
    traverse(node.down, order) 
    if order == Order.POSTORDER: ret.append(node.data) 

當然這是一個線長,但它只有4 if!而非6.

另一種可能性是改變事情以跟蹤所有三個位置,並在事實後插入適當的位置:

def traverse(node, order): 
    if node is None: return 
    prepos = len(ret) 
    traverse(node.right, order) 
    inpos = len(ret) 
    traverse(node.down, order) 
    postpos = len(ret) 
    pos = (prepos, inpos, postpos)[order] 
    ret[pos:pos+1] = node.data 

這將刪除所有的if s,但我不認爲結果更容易閱讀或理解...

真的,使其更易於閱讀和理解的方法可能是切換到功能性算法(遞歸可變算法很少有趣的想法)...但是這只是使三個if機構更大,而不是擺脫它們。