26

I have a list like this:

x = [True, False, True, False]

and a list like this:

y = [a, b, c, d]

I would like to mask x over y to get this output:

output = [a, c]

I know how to do this using while/for loops, but I'm ideally looking for an elegant one-line of code using list comprehension.

0

5 Answers 5

37

You can use zip and a list comprehension to perform a filter operation on y based on corresponding truth values in x:

x = [True, False, True, False]
y = ["a", "b", "c", "d"]

print([b for a, b in zip(x, y) if a])

Output:

['a', 'c']

itertools.compress also does this:

>>> from itertools import compress
>>> x = [True, False, True, False]
>>> y = ["a", "b", "c", "d"]
>>> list(compress(y, x))
['a', 'c']
Sign up to request clarification or add additional context in comments.

Comments

11

I think the easiest way is to use numpy:

import numpy as np
>>> x = [True, False, True, False]
>>> y = ['a', 'b', 'c', 'd']
>>> np.array(y)[x]
array(['a', 'c'], dtype='<U1')

Without numpy, You could also enumerate in a list comprehension:

>>> [i for idx, i in enumerate(y) if x[idx]]
['a', 'c']

3 Comments

I think the list comprehension option does what the OP asks for: an elegant one line solution
@sacul. Why do you replace [a, b, c, d] by ['a', 'b', 'c', 'd']. a, b, c, and d could perfectly represent some kind of object, not necessarily a string
@eapetcho, just so I can display results in my answer, but you're right, those could be an object of some sort.
4

There are several ways to do this.

The simplest way would be to zip the two lists together and use a list comprehension to keep the items you want.

x = [True, False, True, False]
y = ['a', 'b', 'c', 'd']

print([item for keep, item in zip(x, y) if keep])

You can also convert the y array to a numpy array and use the x array to mask the numpy array.

import numpy as np

x = [True, False, True, False]
y = ['a', 'b', 'c', 'd']

print(list(np.array(y)[x]))

Finally, you can create an empty list, iterate through the x and y arrays using their indexes, and append elements in y to the empty list if the corresponding element in x is True.

x = [True, False, True, False]
y = ['a', 'b', 'c', 'd']

temp = []

for index in range(len(y)):
    if x[index]:
        temp.append(y[index])

print(temp)

Comments

2

If already have you some function that returns True/False for each element y, use filter(), example:

list(filter(lambda x: x < 'c' , y))

Or

my_iter = iter([True, False, True, False])
list(filter(lambda x: next(my_iter), y))

Comments

0

This is rather simple to solve. Consider writing properly your list:

x = [True, False, True, False]
y = [a, b, c, d]  # assuming that a, b, c and d are some kind of object
output = []
for i, k in enumerate(x):
    if k:
        output.append(x[i])

1 Comment

Question was: "I know how to do this using while/for loops, but I'm ideally looking for an elegant one-line of code"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.