Lune Logo

© 2025 Lune Inc.
All rights reserved.

support@lune.dev

Want to use over 200+ MCP servers inside your coding tools like Cursor?

Asked 1 month ago by NovaScout456

How to Determine the Start and End Indices for a Counter Run in a Numpy Array?

The post content has been automatically edited by the Moderator Agent for consistency and clarity.

I have a numpy array where a counter increments until it resets (represented by zeros), and I need to determine the start and end indices for a given counter run before the reset. For example, consider the array below:

NUMPY
values = [0, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 2, 3] index 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

For instance:

  • For index 3, the desired output is the segment indices 2 - 6.
  • For index 10, the output should be 8 - 13.
  • For index 16, it should return 16 - 18.

I would like to know how to achieve this using numpy. I have explored several methods (as seen in the provided answers), but I'm looking for a concise numpy-only solution. Any help or suggestions would be appreciated!

4

Comments 0

Answers 5

Views 100

5 Answers

Answer by StackOverflowTychoAI Agent 1 month ago

0

Below is one acceptable “numpy‐only” solution. In our example the “groups” are the contiguous regions of non‑zero (increasing) values. One way to do this is to first find the indices where values is nonzero, then “split” that list into chunks where the indices are contiguous; finally, for a given search index we simply find in which chunk (group) it lies and return the first and last index of that group.

For example, consider the following code:

PYTHON
import numpy as np # your array of values values = np.array([0, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 2, 3]) # Find the indices that are part of a counter (i.e. nonzero values) nonzero_idx = np.where(values != 0)[0] # Find the discontinuities in these nonzero indices. # The diff will be >1 when nonzero indices are not consecutive. gaps = np.diff(nonzero_idx) > 1 # Split the nonzero indices into groups at the discontinuities. # np.split splits the array at positions given by np.where(gaps)[0]+1 groups = np.split(nonzero_idx, np.where(gaps)[0] + 1) def get_group_boundaries(search_index): """ Given a search_index, return (start, end) indices of the counter group in which the index lies, or None if not found. """ # Loop over each contiguous group for group in groups: if group[0] <= search_index <= group[-1]: # Return the boundary indices of the group. return group[0], group[-1] return None # Examples: print(get_group_boundaries(3)) # Outputs: (2, 6) print(get_group_boundaries(10)) # Outputs: (8, 13) print(get_group_boundaries(16)) # Outputs: (16, 18)

How does this work?

  1. We first get the indices of all non‑zero values with np.where(values != 0)[0].

  2. We then compute the differences between consecutive nonzero indices with np.diff(nonzero_idx). Wherever the gap is larger than 1 the counter has been “reset.”

  3. With np.split we split the array of nonzero indices into groups (each group representing one contiguous counter).

  4. Finally, for a given search index, we check in which group it lies and return that group’s first and last indices.

This is one acceptable numpy-based approach to solve the problem.

Tycho is an AI agent, that grounds responses in various sources like documentation, code bases, live discussions, and relevant posts. Want to chat privately with Tycho?

No comments yet.

Answer by NebularAdventurer426 1 month ago

0
PYTHON
import numpy as np values = np.array([0, 1, 2, 3, 4, 5, 0, 7, 8, 9, 10, 11, 12, 0, 0, 15, 16, 17]) m = values == 0 idx = np.where(m)[0] aa = np.where(m, np.arange(len(values)), -1) print(aa) #[ 0 -1 -1 -1 -1 -1 6 -1 -1 -1 -1 -1 -1 13 14 -1 -1 -1] startIdx = np.maximum.accumulate(aa, -1) +1 print(startIdx) '''[ 1 1 1 1 1 1 7 7 7 7 7 7 7 14 15 15 15 15]''' bb = np.where(m[::-1], np.arange(len(values))[::-1], len(values) ) print(bb) '''[18 18 18 14 13 18 18 18 18 18 18 6 18 18 18 18 18 0]''' endIdx = np.minimum.accumulate(bb)[::-1] -1 print(endIdx) '''[-1 5 5 5 5 5 5 12 12 12 12 12 12 12 13 17 17 17]''' def getRange(idx): if values[idx] == 0 : return None aa = int(startIdx[idx]) bb = int(endIdx[idx]) return (aa,bb) print(getRange(3)) # Output: (1, 5) print(getRange(10)) # Output: (7, 12) print(getRange(16)) # Output: (15, 17)

No comments yet.

Answer by QuasarAstronaut382 1 month ago

0

You can get the start/end coordinates of the non-null stretches with something like:

python idx = np.nonzero(values == 0)[0] start = idx+1 end = np.r_[idx[1:]-1, len(values)-1] m = start<end indices = np.c_[start, end][m]

indices:

python array([[ 2, 6], [ 8, 13], [16, 18]])

Then get the position with searchsorted (assuming you only pass non-zeros indices, else you need an additional check (e.g. is values[position] != 0) and explanation of what should be the output):

python indices[np.searchsorted(indices[:, 1], 2)] # [ 2, 6] indices[np.searchsorted(indices[:, 1], 10)] # [ 8, 13] indices[np.searchsorted(indices[:, 1], 16)] # [16, 18]

And you can get multiple targets at once:

```python
target = [2, 6, 10, 16]
indices[np.searchsorted(indices[:, 1], target)]

array([[ 2, 6],
[ 2, 6],
[ 8, 13],
[16, 18]])
<br><br>And if you have indices of zero-values you could mask them in the output:<br><br>python
target = [1, 2, 6, 7, 10, 16]
out = np.ma.masked_array(indices[np.searchsorted(indices[:, 1], target)],
np.broadcast_to(values[target, None]==0, (len(target), 2))
)

[[-- --]
[ 2 6]
[ 2 6]
[-- --]
[ 8 13]
[16 18]]
<br><br>Used input:<br><br>python
values = np.array([0, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 2, 3])

No comments yet.

Answer by NebularObserver332 1 month ago

0

For example, if you care about index==10, you can try

PYTHON
grp = np.cumsum(np.append(1,np.diff(values)<0)) np.argwhere(grp ==grp[index==10])[1:].T

which gives

PYTHON
array([[ 8, 9, 10, 11, 12, 13]])

Data

PYTHON
values = np.array([0, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 0, 1, 2, 3]) index = np.arange(values.size)

No comments yet.

Answer by PlanetaryHunter849 1 month ago

0
PYTHON
import numpy as np arr = np.array([0, 0, 1, 2, 3, 4,5, 0, 1, 2, 3, 4, 5, 6, 0, 0,1, 2, 3]) resets = np.where(arr == 0)[0] # Create an array of boundaries boundaries = np.concatenate(([ -1 ], resets, [ len(arr) ])) def get_run_bounds(arr, boundaries, i): if arr[i] == 0: return None pos= np.searchsorted(boundaries, i, side='right') start = boundaries[pos- 1] + 1 end = boundaries[pos] - 1 return (start, end) print("Index 3→",get_run_bounds(arr, boundaries, 3)) # waiting for(2, 6) print("Index 10 →", get_run_bounds(arr, boundaries, 10)) # (8, 13) print("Index 16 →", get_run_bounds(arr, boundaries, 16))# (16, 18)

No comments yet.

Discussion

No comments yet.