Reputation: 95
I have a list of values:
a = [1,2,3,4]
And a corresponding list of Booleans:
b = [True, True, False, True]
I want to map b onto a such that I get all values in a such that their corresponding value in b is 'True'. So the answer in this instance would be [1,2,4]
The only way I can think of doing is to loop through the elements of b, get the indices that are True, and then retrieve the corresponding index in a. So something like:
def maplist(l1, l2):
# list1 is a list of Booleans to map onto list2
l2_true = []
for el in range(len(l1)):
if l1[el] == True:
l2_true.append(l2[el])
return l2_true
Is there a better way to do this?
Upvotes: 0
Views: 910
Reputation: 2309
I know that the question states two lists, and doesn't mention numpy. But if you will consider using it, and given that a and b are numpy arrays, the mapping operation becomes trivial:
a[b]
I've taken the liberty of benchmarking the suggested options, using 1000x elements:
import numpy
a = [1,2,3,4] * 1000
b = [True, True, False, True] * 1000
def question_fn():
l2_true = []
for el in range(len(a)):
if b[el] == True:
l2_true.append(a[el])
return l2_true
def suggestion_1():
return [v for i, v in enumerate(a) if b[i]]
def suggestion_2():
return [x for x,y in zip(a,b) if y]
x = numpy.array(a)
y = numpy.array(b)
def using_numpy():
return x[y]
python -m timeit -s 'import so' 'so.question_fn()'
1000 loops, best of 3: 453 usec per loop
python -m timeit -s 'import so' 'so.suggestion_1()'
10000 loops, best of 3: 203 usec per loop
python -m timeit -s 'import so' 'so.suggestion_2()'
1000 loops, best of 3: 238 usec per loop
python -m timeit -s 'import so' 'so.using_numpy()'
10000 loops, best of 3: 23 usec per loop
Please note that the numpy timing does not include converting to arrays, otherwise it would be much slower than all of the other suggested solutions. But, if using numpy arrays from the start is an option, it might a viable solution.
Upvotes: 1
Reputation: 208705
Here is a list comprehension that should do what you want:
[v for i, v in enumerate(a) if b[i]]
Another approach:
[x for x, y in zip(a, b) if y]
Upvotes: 4