使用Python编写开关案例并进行比较的有效方法

时间:2019-03-22 23:29:09

标签: python switch-statement

我通常使用Dictionary实现Case / Case进行相等比较。

dict = {0:'zero', 1:'one', 2:'two'}; 
a=1; res = dict[a]

代替

if a==0 :
  res = 'zero'
elif a == 1:
  res = 'one'
elif a==2:
  res = 'two'

是否有一种策略可以实施类似的方法进行非相等比较?

if score <=10 :
  cat = 'A'
elif score >10 and score <=30:
  cat = 'B'
elif score >30 and score <=50 :
  cat = 'C'
elif score >50 and score <=90 :
  cat = 'D'
else:
  cat = 'E'

我知道使用<,<=,>,> =可能会有些棘手,但是有没有什么策略可以概括这一点或从例如列表中生成自动语句

{[10]:'A', [10,30]:'B', [30,50]:'C',[50,90]:'D',[90]:'E'}

和一些标志来说明它是<还是<=

7 个答案:

答案 0 :(得分:1)

bisect模块可用于此类分类问题。特别是,文档提供了example,可以解决与您非常相似的问题。

以下是适用于您的用例的相同示例。该函数返回两个值:字母等级和一个bool标志,该标志指示匹配是否正确。

from bisect import bisect_left

grades = "ABCDE"
breakpoints = [10, 30, 50, 90, 100]

def grade(score):
          index = bisect_left(breakpoints, score)
          exact = score == breakpoints[index]
          grade = grades[index]
          return grade, exact

grade(10) # 'A', True
grade(15) # 'B', False

在上面,我假设您的上一个断点是100的{​​{1}}。如果您确实不希望使用上限,请注意,您可以将E替换为100,以保持代码正常工作。

答案 1 :(得分:1)

是的,有一种策略,但不如人类的思维模式那么清晰。首先,一些注意事项:

  • 还有其他有关“ Python开关”的问题;我假设您已经咨询过他们,并从考虑中删除了这些解决方案。
  • 您发布的结构不是 一个list;这是对dict的无效尝试。密钥必须是可散列的;您提供的列表不是有效的密钥。
  • 您在这里有两种不同的比较类型:与下限的完全匹配和范围限制。

也就是说,我将保留查找表的概念,但是将其放到一个较低的公分母中,以使其易于理解和进行其他考虑。

low = [10, 30, 50, 90]
grade = "ABCDE"

for idx, bkpt in enumerate(low):
    if score <= low:
        exact = (score == low)
        break

cat = grade[idx]

exact是您请求的标志。

答案 2 :(得分:1)

对于您的特定情况,将分数转换为 O(1)时间复杂度的有效方法是使用100减去分数除以10作为字符串索引来获取字母成绩:

def get_grade(score):
    return 'EDDDDCCBBAA'[(100 - score) // 10]

这样:

print(get_grade(100))
print(get_grade(91))
print(get_grade(90))
print(get_grade(50))
print(get_grade(30))
print(get_grade(10))
print(get_grade(0))

输出:

E
E
D
C
B
A
A

答案 3 :(得分:1)

字典可以包含很多值,如果范围不太宽,则可以通过编程扩展每个范围,从而制作出与相等条件字典相似的字典:

from collections import defaultdict

ranges   = {(0,10):'A', (10,30):'B', (30,50):'C',(50,90):'D'}
valueMap = defaultdict(lambda:'E')
for r,letter in ranges.items(): 
    valueMap.update({ v:letter for v in range(r[0],r[1]) })

valueMap[701] # 'E'
valueMap[7] # 'A'

您还可以从if / elif语句中删除多余的条件,并对其格式进行一些更改。这几乎就像一个案例声明:

if   score < 10 : cat = 'A'
elif score < 30 : cat = 'B'
elif score < 50 : cat = 'C'
elif score < 90 : cat = 'D'
else            : cat = 'E'

要求重复分数<您可以定义一个案例函数并将其与以下值一起使用:

score = 43
case = lambda x: score < x
if   case(10): cat = "A"
elif case(30): cat = "B"
elif case(50): cat = "C"
elif case(90): cat = "D"
else         : cat = "E"
print (cat) # 'C'

您可以通过创建一个switch函数来概括此情况,该函数将返回一个“ case”函数,该函数适用于具有通用比较模式的测试值:

def switch(value):
    def case(check,lessThan=None):
        if lessThan is not None:
            return (check is None or check <= value) and value < lessThan
        if type(value) == type(check): return value == check
        if isinstance(value,type(case)): return check(value)
        return value in check
    return case

此通用版本允许进行各种组合:

score = 35
case = switch(score)
if   case(0,10)         : cat = "A"
elif case([10,11,12,13,14,15,16,17,18,19]): 
                          cat = "B"
elif score < 30         : cat = "B" 
elif case(30) \
  or case(range(31,50)) : cat = 'C'
elif case(50,90)        : cat = 'D'
else                    : cat = "E"
print(cat) # 'C'

当您需要做的就是返回一个值时,还有另一种使用lambda函数的方法:

score = 41
case  = lambda x,v: v if score<x else None
cat   = case(10,'A') or case(20,'B') or case(30,'C') or case(50,'D') or 'E' 
print(cat) # "D"

最后一个也可以使用列表理解和映射表来表达:

mapping = [(10,'A'),(30,'B'),(50,'C'),(90,'D')]
scoreCat = lambda s: next( (L for x,L in mapping if s<x),"E" )

score = 37
cat = scoreCat(score) 
print(cat) #"D"

答案 4 :(得分:1)

Python 3.10 引入了 match 大小写(基本上是 switch),您可以将其用作

def check_number(no):
  match no:
    case 0:
      return 'zero
    case 1:
      return 'one'
    case 2:
      return 'two'
    case _:
      return "Invalid num"

这是我尝试的示例。 enter image description here

答案 5 :(得分:0)

low = [10,30,50,70,90]
gradE = "FEDCBA"

def grade(score):
    for i,b in enumerate(low):
        #if score < b:   # 0--9F,10-29E,30-49D,50-69C,70-89B,90-100A Easy
        if score <= b:   # 0-10F,11-30E,31-50D,51-70C,71-90B,91-100A Taff
            return gradE[i]
    else:return gradE[-1]

for score in range(0,101):
    print(score,grade(score))

答案 6 :(得分:0)

Python 没有 case 语句,只需编写一长串 elif。

if score <=10 :
  return 'A'
if score <=30:
  return 'B'
if score <=50 :
  return 'C'
if score <=90 :
  return 'D'
return 'E'

像查字典这样的东西听起来不错,但实际上,它太慢了,elifs 打败了他们。