命令式至函數式隨記(二)

来源:互联网 发布:js人民币小写转大写 编辑:程序博客网 时间:2024/05/15 05:42

English

使用迴圈循序處理List中元素的問題,基本上都可轉為遞迴解,不必使用計數器,只要有辦法取List的head與tail就可以了。如果迴圈中又有迴 圈,基本上就是處理兩個問題了,函數式就是強迫你要分解問題。舉例來說:


def toPFix(infix, isPost):
    expr = infix if isPost else infix[::-1]
    stack = []
    output = []
    toStack, toOutput = ('(', ')') if isPost else (')', '(')
    for c in expr:
        if c == toStack:
            stack.append(c)
        elif c in ['+', '-', '*', '/']:
            while stack and priority(stack[-1]) >= priority(c):
                output.append(stack.pop())
            stack.append(c)
        elif c == toOutput:
            while stack[-1] != toStack:
                output.append(stack.pop())
            stack.pop()
        else:
            output.append(c)
    while stack:
        output.append(stack.pop())
    return ''.join(output if isPost else output[::-1])

好幾個迴圈是吧!基本上從最內層開始,除了無窮迴圈之外,迴圈都會有終止條件,要將之轉為遞迴終止條件,所以函數式一定會要思考邊界在哪,先處理for中 第一個while迴圈:
    
def toPFix(infix, isPost):
    expr = infix if isPost else infix[::-1]
    stack = []
    output = []
    toStack, toOutput = ('(', ')') if isPost else (')', '(')
    
    def procOpt(c, stack, output):
        if stack == [] or priority(stack[-1]) < priority(c):
            return (stack + [c], output)
        else:
            return procOpt(c, stack[0:-1], output + stack[-1:])
    
    for c in expr:
        if c == toStack:
            stack.append(c)
        elif c in ['+', '-', '*', '/']:
            # while stack and priority(stack[-1]) >= priority(c):
            #    output.append(stack.pop())
            # stack.append(c)
            stack, output = procOpt(c, stack, output)
        elif c == toOutput:
            while stack[-1] != toStack:
                output.append(stack.pop())
            stack.pop()
        else:
            output.append(c)
    while stack:
        output.append(stack.pop())
    return ''.join(output if isPost else output[::-1])

procOpt就是一個子問題的解法,所以先讓它傳回值指定給for中的stack與output,從命令式到函數式要多練習,不要急著一次把所有命令式 改為函數式,要一個一個來,不然會一團亂,精神就是分解問題,解決問題。接著類似的,處理for中第二個while迴圈:
def toPFix(infix, isPost):
    expr = infix if isPost else infix[::-1]
    stack = []
    output = []
    toStack, toOutput = ('(', ')') if isPost else (')', '(')
    
    def procOpt(c, stack, output):
        if stack == [] or priority(stack[-1]) < priority(c):
            return (stack + [c], output)
        else:
            return procOpt(c, stack[0:-1], output + stack[-1:])
    
    def procPhs(stack, output):
        if stack[-1] == toStack:
            return (stack[0:-1], output)
        else:
            return procPhs(stack[0:-1], output + stack[-1:])
    
    for c in expr:
        if c == toStack:
            stack.append(c)
        elif c in ['+', '-', '*', '/']:
            stack, output = procOpt(c, stack, output)
        elif c == toOutput:
            # while stack[-1] != toStack:
            #    output.append(stack.pop())
            # stack.pop()
            stack, output = procPhs(stack, output)
        else:
            output.append(c)
    while stack:
        output.append(stack.pop())
    return ''.join(output if isPost else output[::-1])

現在for中沒有迴圈了,記得迴圈就是要當作子問題來處理。最後來料理for迴圈:
def toPFix(infix, isPost):
    toStack, toOutput = ('(', ')') if isPost else (')', '(')
    
    def procOpt(c, stack, output):
        if stack == [] or priority(stack[-1]) < priority(c):
            return (stack + [c], output)
        else:
            return procOpt(c, stack[0:-1], output + stack[-1:])
    
    def procPhs(stack, output):
        if stack[-1] == toStack:
            return (stack[0:-1], output)
        else:
            return procPhs(stack[0:-1], output + stack[-1:])
            
    def procExpr(expr, stack = [], output = []):
        if expr == "":
            return output + stack[::-1]
        elif expr[0] == toStack:
            return procExpr(expr[1:], stack + [expr[0]], output)
        elif expr[0] in ['+', '-', '*', '/']:
            return procExpr(expr[1:], *procOpt(expr[0], stack, output))
        elif expr[0] == toOutput:
            return procExpr(expr[1:], *procPhs(stack, output))
        else:
            return procExpr(expr[1:], stack, output + [expr[0]])
    
    output = procExpr(infix if isPost else infix[::-1])
    return ''.join(output if isPost else output[::-1])
    
注意一下!本來函式中最後一個while迴圈到哪去了?就是procExpr中第一個if中的stack[::-1],因為最後一個while就是將 stack中元素逐一取出,並附加至output後,這不就表示直接將stack反轉再與output串在一起,如果自己寫遞迴函式來反轉程式也是可以, 不過Python中只要用stack[::-1],意思相同。
原创粉丝点击