- For a 3M element container, this answer is
67.2 times
faster than the accepted answer.
- This can be accomplished with
numpy
, by converting the list
to a numpy.array
.
- The code for his answer, is a modification of the code from Find index where elements change value numpy.
- That question wanted all transitions
v[:-1] != v[1:]
, not just the small to large transitions, v[:-1] < v[1:]
, in this question.
- Create a Boolean array, by comparing the array to itself, shifted by one place.
- Use
np.where
to return the indices for True
- This finds the index before the change, because the arrays are shifted for comparison, so use
+1
to get the correct value.
import numpy as np
v = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0]
# convert to array
v = np.array(v)
# create a Boolean array
map_ = v[:-1] < v[1:]
# return the indices
idx = np.where(map_)[0] + 1
print(idx)
[out]:
array([ 7, 24], dtype=int64)
%timeit
# v is 3M elements
v = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0] * 100000
# accepted answer
%timeit [i for i,m in enumerate(v) if i and m and not v[i-1]]
[out]:
336 ms ± 14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# this answer
v = np.array(v)
%timeit np.where(v[:-1] < v[1:])[0] + 1
[out]:
5.03 ms ± 85.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)