Reputation: 43
I'm looking for the most beautiful and short way to multiply those types of lists:
a = [True, False, True, False, False]
b = [100, 200]
Length of b equals to number of True elements in a
The answer that I need is [100, 0, 200, 0, 0]
here
Are there any simple ways to get that answer?
It looks like element-wise multiplication, but the fact is that the size of the second list is smaller, so common numpy methods don't work without bad code.
Hope, you'll find nice solution
Upvotes: 4
Views: 4126
Reputation: 14399
Swiping a bit from @AGN above
c = np.zeros_like(a, dtype = b.dtype)
c[a] = b
Upvotes: 1
Reputation: 51395
You could do this in numpy
:
c = np.array(a).astype(int)
c[c==1] = b
>>> c
array([100, 0, 200, 0, 0])
Note If you need the result as a list (based on your desired output), rather than a numpy
array, use c.tolist()
Upvotes: 10
Reputation: 8378
Another option is to use either numpy.place()
or numpy.put()
:
c = np.zeros_like(a, dtype=np.result_type(b))
np.place(c, a, b)
or
c = np.zeros_like(a, dtype=np.result_type(b))
np.put(c, np.flatnonzero(a), b)
I prefer the first option.
Generate larger data set:
In [39]: a = np.random.randint(0, 2, 100000).astype(np.bool_)
In [40]: b = np.random.randint(0, 100000, np.sum(a))
@sacul solution:
In [41]: %timeit c = np.array(a).astype(int); c[c==1] = b
621 µs ± 13.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
My first option:
In [42]: %timeit c = np.zeros_like(a, dtype=np.result_type(b)); np.place(c, a, b)
462 µs ± 8.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
Upvotes: 2
Reputation: 61032
There's a pretty clean iterator based solution
it = iter(b)
[next(it) if x else 0 for x in a]
# [100, 0, 200, 0, 0]
Upvotes: 7