Skip to content

How to Find Index of List Elements Meeting a Condition in Python

Learn Python methods to find all indices or the first index of list elements that meet a specific condition using list comprehensions, next() with generator expressions, or loops with enumerate().

When working with lists in Python, you often need to find the position (index) of elements that satisfy a specific criteria. You might need the index of the first element that meets the condition, or the indices of all elements that do.

This guide demonstrates several Pythonic ways to find the index (or indices) of list elements based on a condition, using list comprehensions, generator expressions with next(), and loops with enumerate().

The Goal: Finding Indices by Condition

Given a list, we want to identify the numerical positions (indices) of the elements that pass a certain test (e.g., elements greater than 10, elements starting with 'a', even numbers, etc.).

Finding ALL Indices That Meet a Condition

These methods return a list containing the indices of every element satisfying the condition.

List comprehensions provide a concise and readable way to build a new list by iterating over an existing one and applying a condition. We iterate through the indices of the list and check the condition using the index.

def find_all_indices_comp(data_list, condition_func):
  """Finds all indices where list elements meet the condition using list comp."""
  return [index for index, item in enumerate(data_list) if condition_func(item)]

my_list = [5, 12, 8, 15, 6, 20]

indices_gt_10 = find_all_indices_comp(my_list, lambda x: x > 10)
print(f"List: {my_list}")
print(f"Indices where item > 10: {indices_gt_10}")

indices_even = find_all_indices_comp(my_list, lambda x: x % 2 == 0)
print(f"Indices where item is even: {indices_even}")

str_list = ["apple", "banana", "apricot", "blueberry"]
indices_a = find_all_indices_comp(str_list, lambda s: s.startswith('a'))
print(f"List: {str_list}")
print(f"Indices where item starts with 'a': {indices_a}")
  • enumerate(data_list): Efficiently provides pairs of (index, item) during iteration.
  • [index for index, item in ... if condition_func(item)]: The list comprehension. It includes the index in the new list only if condition_func(item) returns True.

Using a for Loop with enumerate()

A standard for loop achieves the same result, offering more explicit steps.

def find_all_indices_loop(data_list, condition_func):
  """Finds all indices where list elements meet the condition using a loop."""
  matching_indices = [] # Initialize an empty list
  for index, item in enumerate(data_list):
    if condition_func(item):
      matching_indices.append(index) # Add index if condition met
  return matching_indices

my_list = [5, 12, 8, 15, 6, 20]
indices_gt_10_loop = find_all_indices_loop(my_list, lambda x: x > 10)
print(f"Indices where item > 10 (loop): {indices_gt_10_loop}")

This approach is functionally equivalent to the list comprehension but more verbose.

Using NumPy (Optional)

If you are already working with NumPy arrays, numpy.where() or numpy.nonzero() are highly efficient.

import numpy as np

my_np_array = np.array([5, 12, 8, 15, 6, 20])

condition = my_np_array > 10

indices_np = np.where(condition)[0] # Get the first (and only) array from the tuple

print(f"NumPy Array: {my_np_array}")
print(f"Indices where item > 10 (NumPy): {indices_np}")

This is best suited when your data is already in NumPy arrays for numerical computation.

Finding the Index of the FIRST Element That Meets a Condition

These methods stop searching and return the index as soon as the first matching element is found.

This is arguably the most elegant and efficient Pythonic way to find the first match.

def find_first_index_next(data_list, condition_func, default=None):
  """Finds the index of the first element meeting the condition using next()."""
  generator = (index for index, item in enumerate(data_list) if condition_func(item))
  return next(generator, default)

my_list = [5, 8, 12, 15, 6, 20]

first_index_gt_10 = find_first_index_next(my_list, lambda x: x > 10)
print(f"List: {my_list}")
print(f"Index of first item > 10: {first_index_gt_10}")         # Output: Index of first item > 10: 2

if first_index_gt_10 is not None:
    print(f"--> The element is: {my_list[first_index_gt_10]}")  # Output: --> The element is: 12

first_index_gt_50 = find_first_index_next(my_list, lambda x: x > 50)
print(f"Index of first item > 50: {first_index_gt_50}")         # Output: Index of first item > 50: None
  • (index for index, item in ... if condition_func(item)): A generator expression that yields the index of matching items.
  • next(generator, default): Attempts to get the first item yielded by the generator. If the generator yields at least one index, next() returns the first one. If the generator is exhausted without yielding anything (meaning no element met the condition), next() returns the default value (None in this case). Providing a default prevents a StopIteration error.

Using a for Loop with enumerate() and break

A for loop can also find the first matching index. The break statement is crucial to stop iterating after the first match is found.

def find_first_index_loop(data_list, condition_func, default=None):
  """Finds the index of the first element meeting the condition using a loop."""
  index_first_match = default # Initialize with default
  for index, item in enumerate(data_list):
    if condition_func(item):
      index_first_match = index # Found it! Assign index
      break # Stop searching
  return index_first_match

my_list = [5, 8, 12, 15, 6, 20]

first_index_gt_10_loop = find_first_index_loop(my_list, lambda x: x > 10)
print(f"Index of first item > 10 (loop): {first_index_gt_10_loop}") # Output: Index of first item > 10 (loop): 2

first_index_gt_50_loop = find_first_index_loop(my_list, lambda x: x > 50)
print(f"Index of first item > 50 (loop): {first_index_gt_50_loop}") # Output: Index of first item > 50 (loop): None

This works well but is less concise than the next() approach.

Handling Cases Where No Element Meets the Condition

  • Finding ALL: If no element meets the condition, the list comprehension or loop method will simply return an empty list [].
  • Finding FIRST:
    • The next(generator, default) method gracefully returns the default value (e.g., None) when no match is found. Your calling code should check for this default value.
    • The for loop method requires initializing the result variable to a default value (e.g., None) and checking if it still holds that value after the loop finishes.

Conclusion

Python offers several ways to find the indices of list elements that meet specific conditions:

  • To get all matching indices: A list comprehension using enumerate is often the most Pythonic and readable approach. A for loop provides an alternative. NumPy's where/nonzero are efficient for NumPy arrays.
  • To get the index of the first match: Using next() with a generator expression and enumerate is concise and efficient, especially with a default value to handle no-match cases. A for loop with break is a viable alternative.

Choose the method that best balances readability, conciseness, and performance for your specific needs. Remember to handle the case where no elements satisfy the condition, particularly when searching for the first match.

Navigation