Python elegant assignment based on True/False values

后端 未结 11 1515
日久生厌
日久生厌 2021-01-31 09:32

I have a variable I want to set depending on the values in three booleans. The most straight-forward way is an if statement followed by a series of elifs:

if a a         


        
相关标签:
11条回答
  • 2021-01-31 09:42

    Another option would be to create a helper function:

    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'))
    

    This method assumes that one of the tests passed in will be true. It could also be made lazier with lambdas.

    0 讨论(0)
  • 2021-01-31 09:42

    To measure speeds:

    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)
    

    Result

    0.0480533140385 
    0.0450973517584 
    
    0.0309056039245 
    
    0.0295291720037 
    0.0286550385594 
    
    0.0280122194301 
    0.0266760160858 
    
    0.0249769174574
    
    0 讨论(0)
  • 2021-01-31 09:48

    Since your getting all the combinations, you could create an index based on the values like this:

    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)
    

    output:

    1st
    2nd
    3rd
    4th
    5th
    6th
    7th
    8th
    
    0 讨论(0)
  • 2021-01-31 09:48

    Here is a truth table approach:

    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)]
    
    0 讨论(0)
  • 2021-01-31 09:52

    You can think of a, b, and c as three bits that when put together form a number between 0 and 7. Then, you can have an array of the values ['first', 'second', ... 'eighth'] and use the bit value as an offset into the array. This would just be two lines of code (one to assemble the bits into a value from 0-7, and one to lookup the value in the array).

    Here's the code:

    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)]
    
    0 讨论(0)
  • 2021-01-31 09:58

    if your goal is to avoid writing a lot of "ands" and boolean expressions you can use prime number and only one conditions like this (example for 2 conditions)

     cond = (2**cond_1)*(3**cond_2)
    

    so

    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
    

    This hack can be used for 3 conditions using 3 primes and so on

    Like this...

    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]
    
    0 讨论(0)
提交回复
热议问题