It would be more consistent with python indexing for nonzero_coords([0, 0, 0, 0, 1, 2, 3, 4]) to return (4, 8) than (4, 7) , because [0, 0, 0, 0, 1, 2, 3, 4][4:8] returns [1, 2, 3, 4] .
Here is a function that calculates nonzero intervals. It processes several intervals:
def nonzero_intervals(vec): ''' Find islands of non-zeros in the vector vec ''' if len(vec)==0: return [] elif not isinstance(vec, np.ndarray): vec = np.array(vec) edges, = np.nonzero(np.diff((vec==0)*1)) edge_vec = [edges+1] if vec[0] != 0: edge_vec.insert(0, [0]) if vec[-1] != 0: edge_vec.append([len(vec)]) edges = np.concatenate(edge_vec) return zip(edges[::2], edges[1::2])
If you really want the answer to have end indices included in the island, you can simply change the last line to: return zip(edges[::2], edges[1::2]-1)
Tests:
a = [0, 0, 0, 0, 1, 2, 3, 4] intervals = nonzero_intervals(a) assert intervals == [(4, 8)] a = [1, 2, 3, 4, 0, 0] intervals = nonzero_intervals(a) assert intervals == [(0, 4)] a=[1, 2, 0, 0, 0, 3, 4, 0] intervals = nonzero_intervals(a) assert intervals == [(0, 2), (5, 7)] a = [0, 4, 0, 6, 0, 6, 7, 0, 9] intervals = nonzero_intervals(a) assert intervals == [(1, 2), (3, 4), (5, 7), (8, 9)] a = [1, 2, 3, 4] intervals = nonzero_intervals(a) assert intervals == [(0, 4)] a = [0, 0, 0] intervals = nonzero_intervals(a) assert intervals == [] a = [] intervals = nonzero_intervals(a) assert intervals == []