title: Efficiently return the index of the first value satisfying condition in array
body: <p>I need to find the index of the first value in a 1d NumPy array, or Pandas numeric series, satisfying a condition. The array is large and the index may be near the start <em>or</em> end of the array, <em>or</em> the condition may not be met at all. I can't tell in advance which is more likely. If the condition is not met, the return value should be <code>-1</code>. I've considered a few approaches.</p>
  
  <h3>Attempt 1</h3>
  
  <pre><code># func(arr) returns a Boolean array
  idx = next(iter(np.where(func(arr))[0]), -1)
  </code></pre>
  
  <p>But this is often too slow as <code>func(arr)</code> applies a vectorised function on the <em>entire</em> array rather than stopping when the condition is met. Specifically, it is expensive when the condition is met near the <em>start</em> of the array.</p>
  
  <h3>Attempt 2</h3>
  
  <p><a href="https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.argmax.html" rel="noreferrer"><code>np.argmax</code></a> is marginally faster, but fails to identify when a condition is <em>never</em> met:</p>
  
  <pre><code>np.random.seed(0)
  arr = np.random.rand(10**7)
  
  assert next(iter(np.where(arr &gt; 0.999999)[0]), -1) == np.argmax(arr &gt; 0.999999)
  
  %timeit next(iter(np.where(arr &gt; 0.999999)[0]), -1)  # 21.2 ms
  %timeit np.argmax(arr &gt; 0.999999)                    # 17.7 ms
  </code></pre>
  
  <p><code>np.argmax(arr &gt; 1.0)</code> returns <code>0</code>, i.e. an instance when the condition is <em>not</em> satisfied.</p>
  
  <h3>Attempt 3</h3>
  
  <pre><code># func(arr) returns a Boolean scalar
  idx = next((idx for idx, val in enumerate(arr) if func(arr)), -1)
  </code></pre>
  
  <p>But this is too slow when the condition is met near the <em>end</em> of the array. Presumably this is because the generator expression has an expensive overhead from a large number of <code>__next__</code> calls.</p>
  
  <p>Is this <em>always</em> a compromise or is there a way, for generic <code>func</code>, to extract the first index efficiently?</p>
  
  <h3>Benchmarking</h3>
  
  <p>For benchmarking, assume <code>func</code> finds the index when a value is greater than a given constant:</p>
  
  <pre><code># Python 3.6.5, NumPy 1.14.3, Numba 0.38.0
  import numpy as np
  
  np.random.seed(0)
  arr = np.random.rand(10**7)
  m = 0.9
  n = 0.999999
  
  # Start of array benchmark
  %timeit next(iter(np.where(arr &gt; m)[0]), -1)                       # 43.5 ms
  %timeit next((idx for idx, val in enumerate(arr) if val &gt; m), -1)  # 2.5 µs
  
  # End of array benchmark
  %timeit next(iter(np.where(arr &gt; n)[0]), -1)                       # 21.4 ms
  %timeit next((idx for idx, val in enumerate(arr) if val &gt; n), -1)  # 39.2 ms
  </code></pre>