Search code examples
pythonpython-3.xlist-comprehension

Do not put an item in list if x isn't True


I want to add an item to my list only if a variable is true, but I want to do that in one line to not make my program longer and crappy (because I want to do that on a lot of variables). Let's say I want to return a list, but include items in it only if x and etc are true.

I want to use something that won't add any data to the list, because None is considered as an item.

# Note: The variables name may change, so please make it compatible.
return [data1 if x else None, data2 if y else None]
<< x = False, y = False = [None, None], I want []

Example

# User choose if he wants data(x) by changing the default value of want_data(x)
def func(want_data1=True, want_data2=True):
    return [data1 if want_data1 else None, data2 if want_data2 else None]

print(func(False, False))
<< [None, None] # Not what I want! Excepted output is []

Solution

  • You are working with ternary expressions and they only allow the following syntax, which is equivalent to (expr1, expr2)[condition]

    expr1 if cond else expr2
    

    Even if you try python short-circuiting, it will still return False if x is false and data1 when x is True.

    [x and data1, y and data2]
    

    For your case, you will have to do a list comprehension on top of the ternary opertion you have created as -

    data1 = 'hi'
    data2 = 'there'
    
    x, y = True, False
    
    [i for i in [data1 if x else None, data2 if y else None] if i]
    
    ['hi']
    

    Your function with minimal modification with the above approach:

    def func(want_data1=True, want_data2=True):
        l = [data1 if want_data1 else None, data2 if want_data2 else None]
        return [i for i in l if i]
    

    Alternate approach - If you are open to numpy, its super easy to mask the list then try this:

    import numpy as np
    def func(want_data1=True, want_data2=True):
        return np.array([data1, data2])[[want_data1,want_data2]].tolist()
    

    With a dictionary -

    import numpy as np
    def func(want_data1=True, want_data2=True):
        d = {'data1': data1, 'data2': data2}
        return dict(np.array(list(d.items()))[[want_data1,want_data2]])