如何将一系列条件映射为字典中的键?

问题描述:

我知道你可以使用字典来替代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

您的条件在本质上是连续的;你想要一个接一个地测试,而不是将少量的键映射到这里的值。改变条件的顺序可能会改变结果;值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

您不能使用字典映射任意条件,因为它们中的多个可能同时为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 

没有直接关系,但我经常使用类似下面用于与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