0

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?

1
  • You can also use itertools.compress. For example: list(itertools.compress(a, b)). But I prefer list comprehension solutions. Commented Mar 18, 2013 at 19:29

3 Answers 3

4

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]
Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

0

Or this:

[a[i] for i in range(len(a)) if b[i]]

Comments

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.