For i in range(len(…)) in Python(Beginner’s Guide)

for i in range(len(sequence)) iterates over indices of sequence.

  • i takes values 0 to len(sequence)-1
  • Time complexity: O(n) for sequence of length n
  • Creates new int i each iteration
  • Prefer for item in sequence to iterate over values directly if index not needed

When to Use “for i in range(len(…))” in Python

The construct for i in range(len(sequence)) is a common pattern in Python for iterating over the indices of a sequence (like a list, tuple, or string). It’s often used when you need to access both the index and the value at that index during the iteration.

For example, let’s say you have a list of numbers and you want to print both the index and the value at that index:

numbers = [5, 8, 2, 1, 9]

for i in range(len(numbers)):
    print(f"Index {i}: Value {numbers[i]}")

This will output:

Index 0: Value 5
Index 1: Value 8
Index 2: Value 2
Index 3: Value 1
Index 4: Value 9

In this case, using for i in range(len(numbers)) allows us to iterate over the indices of the numbers list, and then use numbers[i] to access the value at that index.

Sorting a List Based on Another List

One common use case for for i in range(len(...)) is when you need to sort one list based on the values in another list. Here’s an example:

names = ["Alice", "Bob", "Charlie", "David", "Eve"]
ages = [25, 32, 18, 47, 22]

# Sort the names list based on the ages list
sorted_names = [name for age, name in sorted(zip(ages, names))]

print(sorted_names)
# Output: ['Charlie', 'Eve', 'Alice', 'Bob', 'David']

In this example, we use the zip function to create pairs of (age, name) tuples, and then sort those tuples based on the age value. We then use a list comprehension to extract just the name values from the sorted list of tuples.

However, there’s an alternative way to achieve the same result using for i in range(len(...)):

names = ["Alice", "Bob", "Charlie", "David", "Eve"]
ages = [25, 32, 18, 47, 22]

sorted_names = [None] * len(names)

for i in range(len(names)):
    sorted_names[sorted(range(len(ages)), key=ages.__getitem__)[i]] = names[i]

print(sorted_names)
# Output: ['Charlie', 'Eve', 'Alice', 'Bob', 'David']

Here’s how this works:

  1. We create a new list sorted_names with None values, the same length as names.
  2. We use for i in range(len(names)) to iterate over the indices of names.
  3. Inside the loop, we use sorted(range(len(ages)), key=ages.__getitem__) to get a list of indices that would sort the ages list.
  4. We use those sorted indices to assign the corresponding names[i] value to the correct position in sorted_names.

While this approach is more verbose and arguably less readable than the list comprehension version, it demonstrates how for i in range(len(...)) can be used to perform custom sorting operations.

Intentional Programming and Readability

As mentioned in one of the provided answers, using for i in range(len(...)) can sometimes improve code readability and express the intent of the code more clearly. This concept is known as “intentional programming.”

For example, let’s say you want to iterate over a list and perform some operation a fixed number of times, regardless of the values in the list. In this case, using for i in range(len(list)) can make the code more explicit:

my_list = [1, 2, 3, 4, 5]

for _ in range(len(my_list)):
    # Perform some operation here
    print("Operation performed")

Here, we use for _ in range(len(my_list)) to indicate that we want to perform the operation the same number of times as there are elements in my_list, but we don’t actually need to access the values in my_list.

Alternatively, you could use a simple for loop with a counter variable:

my_list = [1, 2, 3, 4, 5]
counter = 0

while counter < len(my_list):
    # Perform some operation here
    print("Operation performed")
    counter += 1

While this approach works, using for i in range(len(...)) can be more concise and easier to read, especially for Python developers who are familiar with this idiom.

When Not to Use “for i in range(len(…))”

While for i in range(len(...)) is a useful construct in certain situations, it’s generally not recommended to use it when iterating over the values of a sequence directly. In those cases, it’s better to use the standard for value in sequence syntax:

# Good
my_list = [1, 2, 3, 4, 5]
for value in my_list:
    print(value)

# Bad
my_list = [1, 2, 3, 4, 5]
for i in range(len(my_list)):
    print(my_list[i])

The second example, while functionally correct, is more verbose and less readable than the first example. It also introduces the potential for off-by-one errors if the loop condition is not written correctly.

Code Examples

Here are a few more code examples demonstrating the use of for i in range(len(...)) in Python:

Reversing a List

my_list = [1, 2, 3, 4, 5]
reversed_list = [None] * len(my_list)

for i in range(len(my_list)):
    reversed_list[len(my_list) - 1 - i] = my_list[i]

print(reversed_list)
# Output: [5, 4, 3, 2, 1]

In this example, we create a new list reversed_list with None values, the same length as my_list. We then use for i in range(len(my_list)) to iterate over the indices of my_list, and assign the values to the corresponding reverse indices in reversed_list.

Removing Duplicate Values from a List

my_list = [1, 2, 3, 2, 4, 1, 5]
unique_list = []

for i in range(len(my_list)):
    if my_list[i] not in unique_list:
        unique_list.append(my_list[i])

print(unique_list)
# Output: [1, 2, 3, 4, 5]

Here, we use for i in range(len(my_list)) to iterate over the indices of my_list. For each index i, we check if the value my_list[i] is already in the unique_list. If not, we add it to unique_list.

Swapping Values in a List

my_list = [1, 2, 3, 4, 5]

for i in range(len(my_list) // 2):
    my_list[i], my_list[len(my_list) - 1 - i] = my_list[len(my_list) - 1 - i], my_list[i]

print(my_list)
# Output: [5, 4, 3, 2, 1]

In this example, we use for i in range(len(my_list) // 2) to iterate over the first half of the indices in my_list. For each index i, we swap the value at index i with the value at the corresponding index from the end of the list (len(my_list) - 1 - i).

These examples demonstrate how for i in range(len(...)) can be used to perform various operations on lists in Python, such as reversing, removing duplicates, and swapping values.