2015-04-03 72 views
13

我知道你可以使用字典來替代switch語句,如以下幾點:如何將一系列條件映射爲字典中的鍵?

def printMessage(mystring): 
    # Switch statement without a dictionary 
    if mystring == "helloworld": 
     print "say hello" 
    elif mystring == "byeworld": 
     print "say bye" 
    elif mystring == "goodafternoonworld": 
     print "good afternoon" 


def printMessage(mystring): 
    # Dictionary equivalent of a switch statement 
    myDictionary = {"helloworld": "say hello", 
        "byeworld": "say bye", 
        "goodafternoonworld": "good afternoon"} 
    print myDictionary[mystring] 

但是如果使用條件下,比返回的錯誤,這些不能被映射真正的平等(==)等作爲容易即:

if i > 0.5: 
    print "greater than 0.5" 
elif i == 5: 
    print "it is equal to 5" 
elif i > 5 and i < 6: 
    print "somewhere between 5 and 6" 

上面不能直接轉換爲一個字典鍵 - 值對作爲是:

# this does not work 
mydictionary = { i > 0.5: "greater than 0.5" } 

甲羊肉DA可以使用,因爲它是散列能,但通過將相同的拉姆達對象到詞典中,而不是當拉姆達的評價是真實的,以獲得結果字符串出地圖的唯一方法:

x = lambda i: i > 0.5 
mydictionary[x] = "greater than 0.5" 
# you can get the string by doing this: 
mydictionary[x] 
# which doesnt result in the evaluation of x 

# however a lambda is a hashable item in a dictionary 
mydictionary = {lambda i: i > 0.5: "greater than 0.5"} 

有誰知道在lambda評估和返回值之間創建映射的技術或方法嗎? (這可能類似於功能語言中的模式匹配)

+0

_「但顯然其唯一可能的情況下本身是由過去了,拉姆達不能當拉姆達的評價是真實的」 _對不起,你能換一種說法?我不明白你的意思。 – Kevin 2015-04-03 14:05:02

+0

@凱文好吧我剛剛編輯了答案,以澄清這一點 – Har 2015-04-03 14:33:11

回答

16

您的條件在本質上是連續的;你想要一個接一個地測試,而不是將少量的鍵映射到這裏的值。改變條件的順序可能會改變結果;值5結果"greater than 0.5"在您的示例中,而不是"it is equal to 5"

使用元組的列表:

myconditions = [ 
    (lambda i: i > 0.5, "greater than 0.5"), 
    (lambda i: i == 5, "it is equal to 5"), 
    (lambda i: i > 5 and i < 6, "somewhere between 5 and 6"), 
] 

後就可以依次訪問每一個直到一個匹配:

for test, message in myconditions: 
    if test(i): 
     return message 

重新排序的測試將更改結果。

一本字典適用於您的第一個示例,因爲有一個簡單的相等性測試針對由字典優化的多個靜態值,但此處不存在此類簡單均等。

+0

括號不是必需的,但這是我即將發佈。 – FunkySayu 2015-04-03 14:07:01

+2

@FunkySayu:他們被要求將lambda和消息分組爲元組。如果不這樣做,則需要笨拙的循環結構。 – 2015-04-03 14:07:50

+0

何好我的壞,我雖然你使用字典,而不是元組列表。順便說一句,如果沒有匹配,你可以在最後添加一個return語句? – FunkySayu 2015-04-03 14:09:08

1

您不能使用字典映射任意條件,因爲它們中的多個可能同時爲true。相反,您需要按順序評估每一個,並在第一次遇到真正的代碼時執行相關的代碼。以下是一種正式實施類似的方法的概述,它甚至允許相當於default:的情況。

from collections import namedtuple 

Case = namedtuple('Case', ['condition', 'code']) 

cases = (Case('i > 0.5', 
      """print 'greater than 0.5'"""), 

     Case('i == 5', 
      """print 'it is equal to 5'"""), 

     Case('i > 5 and i < 6', 
      """print 'somewhere between 5 and 6'""")) 

def switch(cases, **namespace): 
    for case in cases: 
     if eval(case.condition, namespace): 
      exec(case.code, namespace) 
      break 
    else: 
     print 'default case' 

switch(cases, i=5) 

輸出:

greater than 0.5 
0

沒有直接關係,但我經常使用類似下面用於與dictionaruy查找替換級聯IFS例的範例。

def multipleifs(a=None,b=None,c=None,d=None,e=None): 
    """ Func1 with cascaded if 
    >>> multipleifs(10,20,30,40,50) 
    160 
    """ 

    x=10 
    if a: 
     x += 10 
    if b: 
     x += 20 
    if c: 
     x += 30 
    if d: 
     x += 40 
    if e: 
     x += 50 

    return x 

def dictif(a=None,b=None,c=None,d=None,e=None): 
    """ Func2 with dictionary replacing multiple ifs 
    >>> dictif(10,20,30,40,50) 
    160 
    """ 

    x, mydict = 10, dict(enumerate([10,20,30,40,50])) 

    for count, item in enumerate([a,b,c,d,e]): 
     if item: x += mydict.get(count,0) 

    return x 
相關問題