我通常使用字典实现 switch/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'}
还有一些标志表明它是否为 <
或 <=
.
最佳答案
字典可以包含很多值。如果您的范围不是太宽,您可以通过以编程方式扩展每个范围来制作一个类似于您拥有的用于相等条件的字典:
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) })
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 <
,您可以定义一个 case 函数并将其与值一起使用:
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 函数来概括这一点,该函数返回一个“案例”函数,该函数适用于具有通用比较模式的测试值:
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"
更具体地针对这个问题,可以使用根据您的参数返回映射函数的设置函数来创建通用解决方案:
def rangeMap(*breaks,inclusive=False):
default = breaks[-1] if len(breaks)&1 else None
breaks = list(zip(breaks[::2],breaks[1::2]))
def mapValueLT(value):
return next( (tag for tag,bound in breaks if value<bound), default)
def mapValueLE(value):
return next( (tag for tag,bound in breaks if value<=bound), default)
return mapValueLE if inclusive else mapValueLT
scoreToCategory = rangeMap('A',10,'B',30,'C',50,'D',90,'E')
print(scoreToCategory(53)) # D
print(scoreToCategory(30)) # C
scoreToCategoryLE = rangeMap('A',10,'B',30,'C',50,'D',90,'E',inclusive=True)
print(scoreToCategoryLE(30)) # B
请注意,通过使用 bisect,您可以通过多做一些工作来提高返回函数的性能。 模块。
关于Python 写 switch case 的有效方式与比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55309046/