Вот еще один пример с NumPy, специально использующий нарезку массивов -
def islands_info(a):
# Compare consecutive elems for changes. Use `True` as sentients to detect edges
idx = np.flatnonzero(np.r_[True,a[:-1]!=a[1:],True])
# Index into input array with the sliced array until second last array to
# get start indices and the differentiation for the lengths
return np.column_stack((a[idx[:-1]],np.diff(idx)))
Пробный прогон -
In [51]: a = np.array([0, 0, 1, 1, 1, 0, 1, 1, 1, 1])
In [52]: islands_info(a)
Out[52]:
array([[0, 2],
[1, 3],
[0, 1],
[1, 4]])
Если вам нужен вывод в виде списка кортежей -
In [56]: list(zip(*islands_info(a).T))
Out[56]: [(0, 2), (1, 3), (0, 1), (1, 4)]
Сроки -
Сравнение с другим на основе NumPy @yatu
-
In [43]: np.random.seed(a)
In [44]: a = np.random.choice([0,1], 1000000)
In [45]: %timeit yatu(a)
11.7 ms ± 428 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [46]: %timeit islands_info(a)
8.98 ms ± 40.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [47]: np.random.seed(a)
In [48]: a = np.random.choice([0,1], 10000000)
In [49]: %timeit yatu(a)
232 ms ± 3.71 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [50]: %timeit islands_info(a)
152 ms ± 933 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)