我有一个我想要设置的变量,具体取决于三个布尔值中的值。最直接的方式是if语句后跟一系列elifs:
if a and b and c:
name = 'first'
elif a and b and not c:
name = 'second'
elif a and not b and c:
name = 'third'
elif a and not b and not c:
name = 'fourth'
elif not a and b and c:
name = 'fifth'
elif not a and b and not c:
name = 'sixth'
elif not a and not b and c:
name = 'seventh'
elif not a and not b and not c:
name = 'eighth'
这有点尴尬,我想知道是否有更多的Pythonic方法来处理这个问题。想到了几个想法。
字典黑客:
name = {a and b and c: 'first',
a and b and not c: 'second',
a and not b and c: 'third',
a and not b and not c: 'fourth',
not a and b and c: 'fifth',
not a and b and not c: 'sixth',
not a and not b and c: 'seventh',
not a and not b and not c: 'eighth'}[True]
我把它称之为黑客,因为我并不太疯狂,其中七个键是假的并且相互压倒。
和/或魔术
name = (a and b and c and 'first' or
a and b and not c and 'second' or
a and not b and c and 'third' or
a and not b and not c and 'fourth' or
not a and b and c and 'fifth' or
not a and b and not c and 'sixth' or
not a and not b and c and 'seventh' or
not a and not b and not c and 'eighth')
这是有效的,因为Python ands和ors返回要评估的最后一个值,但你必须知道这是为了理解这个奇怪的代码。
这三个选项中没有一个非常令人满意。你推荐什么?
答案 0 :(得分:50)
您可以将a,b和c视为三位,当它们组合在一起形成0到7之间的数字。然后,您可以得到一个值数组['first','second',... 'eight']并使用位值作为数组的偏移量。这只是两行代码(一行用于将位组装成0-7的值,一行用于查找数组中的值)。
以下是代码:
nth = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
nth[(a and 4 or 0) | (b and 2 or 0) | (c and 1 or 0)]
答案 1 :(得分:29)
如何使用字典?
name = {(True, True, True): "first", (True, True, False): "second",
(True, False, True): "third", (True, False, False): "fourth",
(False, True, True): "fifth", (False, True, False): "sixth",
(False, False, True): "seventh", (False, False, False): "eighth"}
print name[a,b,c] # prints "fifth" if a==False, b==True, c==True etc.
答案 2 :(得分:11)
也许不是更好,但是怎么样
results = ['first', 'second', 'third', 'fourth',
'fifth', 'sixth', 'seventh', 'eighth']
name = results[((not a) << 2) + ((not b) << 1) + (not c)]
答案 3 :(得分:5)
如果a,b,c真的是布尔值:
li = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
name = li[a*4 + b*2 + c]
如果他们不是布尔人:
li = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
a,b,c = map(bool,(a,b,c))
name = li[a*4 + b*2 + c]
来自Clint Miller的想法
答案 4 :(得分:2)
由于获得了所有组合,您可以根据以下值创建索引:
def value(a,b,c ):
values = ['8th','7th','6th','5th','4th','3rd','2nd','1st']
index = ( 4 if a else 0 ) + ( 2 if b else 0 ) + ( 1 if c else 0 )
return values[index]
if __name__ == "__main__":
print value(True, True, True )
print value(True, True, False )
print value(True, False, True )
print value(True, False, False )
print value(False, True, True )
print value(False, True, False)
print value(False, False, True )
print value(False, False, False)
输出:
1st
2nd
3rd
4th
5th
6th
7th
8th
答案 5 :(得分:1)
嵌套ifs怎么样 - 这意味着你不必多次检查所有内容并且对我来说更清楚(尽管可能不像其他一些答案那样聪明):
if a:
if b:
if c:
name="first"
else:
name="second"
else:
if c:
name="third"
else:
name="fourth"
else:
if b:
if c:
name="fifth"
else:
name="sixth"
else:
if c:
name="seventh"
else:
name="eighth"
答案 6 :(得分:1)
另一种选择是创建辅助函数:
def first_true(*args):
true_vals = (arg for arg in args if arg[0])
return next(true_vals)[1]
name = first_true((a and b and c, 'first'),
(a and b and not c, 'second'),
(a and not b and c, 'third'),
(a and not b and not c, 'fourth'),
(not a and b and c, 'fifth'),
(not a and b and not c, 'sixth'),
(not a and not b and c, 'seventh'),
(not a and not b and not c, 'eighth'))
此方法假定传入的其中一个测试将为true。也可以用lambdas使它变得更加懒散。
答案 7 :(得分:1)
测量速度:
from time import clock
a,b,c = True,False,False
A,B,C,D,E,F,G,H = [],[],[],[],[],[],[],[]
for j in xrange(30):
te = clock()
for i in xrange(10000):
name = (a and b and c and 'first' or
a and b and not c and 'second' or
a and not b and c and 'third' or
a and not b and not c and 'fourth' or
not a and b and c and 'fifth' or
not a and b and not c and 'sixth' or
not a and not b and c and 'seventh' or
not a and not b and not c and 'eighth')
A.append(clock()-te)
te = clock()
for i in xrange(10000):
if a and b and c:
name = 'first'
elif a and b and not c:
name = 'second'
elif a and not b and c:
name = 'third'
elif a and not b and not c:
name = 'fourth'
elif not a and b and c:
name = 'fifth'
elif not a and b and not c:
name = 'sixth'
elif not a and not b and c:
name = 'seventh'
elif not a and not b and not c:
name = 'eighth'
B.append(clock()-te)
#=====================================================================================
li = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
te = clock()
for i in xrange(10000):
name = li[a*4 + b*2 + c]
C.append(clock()-te)
#=====================================================================================
nth = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
te = clock()
for i in xrange(10000):
name = nth[(a and 4 or 0) | (b and 2 or 0) | (c and 1 or 0)]
D.append(clock()-te)
nth = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
te = clock()
for i in xrange(10000):
name = nth[(a and 4 or 0) + (b and 2 or 0) + (c and 1 or 0)]
E.append(clock()-te)
#=====================================================================================
values = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
te = clock()
for i in xrange(10000):
name = values[( 4 if a else 0 )| ( 2 if b else 0 ) | ( 1 if c else 0 )]
F.append(clock()-te)
values = ['eighth', 'seventh', 'sixth', 'fifth', 'fourth', 'third', 'second', 'first']
te = clock()
for i in xrange(10000):
name = values[( 4 if a else 0 ) + ( 2 if b else 0 ) + ( 1 if c else 0 )]
G.append(clock()-te)
#=====================================================================================
dic = {(True, True, True): "first",
(True, True, False): "second",
(True, False, True): "third",
(True, False, False): "fourth",
(False, True, True): "fifth",
(False, True, False): "sixth",
(False, False, True): "seventh",
(False, False, False): "eighth"}
te = clock()
for i in xrange(10000):
name = dic[a,b,c]
H.append(clock()-te)
print min(A),'\n', min(B),'\n\n', min(C),'\n\n', min(D),'\n',min(E),'\n\n',min(F),'\n', min(G),'\n\n', min(H)
结果
0.0480533140385
0.0450973517584
0.0309056039245
0.0295291720037
0.0286550385594
0.0280122194301
0.0266760160858
0.0249769174574
答案 8 :(得分:0)
我会选择@OscarRyz,@ Clint和@Sven的列表/位解决方案,但这是另一个:
S1 = frozenset(['first', 'second', 'third', 'fourth'])
S2 = frozenset(['first', 'second', 'fifth', 'sixth'])
S3 = frozenset(['first', 'third', 'fifth', 'seventh'])
last = 'eighth'
empty = frozenset([])
def value(a, b, c):
for r in (a and S1 or empty) & (b and S2 or empty) & (c and S3 or empty):
return r
return last
答案 9 :(得分:0)
如果你的目标是避免编写大量的“ands”和布尔表达式,你可以使用素数而只有一个这样的条件(2个条件的例子)
cond = (2**cond_1)*(3**cond_2)
所以
cond == 1 #means cond_1 and cond_2 are False
cond == 2 #means cond_1 is True and con_2 is False
cond == 3 #means cond_1 is False and con_2 is True
cond == 6 #means con_1 and Con_2 are True
这个hack可以用于3个条件,使用3个素数等等
喜欢这个......
cond = (2**a)*(3**b)*(5**c)
name = {30:'first', 6: 'second', 10:'third', 2:'fourth',
15:'fifth', 3:'sixth', 5:'seventh', 1:'eighth'}[cond]
答案 10 :(得分:-1)
这是一个真值表方法:
lookup = {'000': 'eighth',
'001': 'seventh',
'010': 'sixth',
'011': 'fifth',
'100': 'fourth',
'101': 'third',
'110': 'second',
'111': 'first'}
def key(a, b, c):
return ''.join([str(a),str(b),str(c)])
name = lookup[key(0,1,1)]