Table of Contents
- Introduction to Loops
- Why Loops Are Essential
- Types of Loops
- For Loop
- While Loop
- Do-While Loop
- For-Each / Enhanced For Loop
- Loop Control Statements
- Nested Loops
- Infinite Loops
- Loop Performance
- Common Loop Patterns
- Language-Specific Examples
- Best Practices
- Common Pitfalls
- Conclusion
Introduction to Loops
Loops are programming constructs that allow you to execute a block of code repeatedly. They are fundamental to programming and are used whenever you need to perform repetitive tasks efficiently.
What Are Loops?
# Without loops - repetitive, error-prone
print("Hello")
print("Hello")
print("Hello")
print("Hello")
print("Hello")
# With loops - concise, maintainable
for i in range(5):
print("Hello")
The Problem Loops Solve
// Imagine processing 1000 items without loops
processItem(item0);
processItem(item1);
processItem(item2);
// ... 997 more lines ...
// With loops - 3 lines instead of 1000
for (let i = 0; i < items.length; i++) {
processItem(items[i]);
}
Why Loops Are Essential
Efficiency
# Calculate sum of numbers 1 to 1,000,000 # Without loop (impossible to write manually) # With loop - simple and efficient total = 0 for i in range(1, 1000001): total += i print(total)
Code Reusability
// Same logic applied to different data
const numbers = [1, 2, 3, 4, 5];
const names = ["Alice", "Bob", "Charlie"];
// Same loop pattern works for any array
for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}
for (let i = 0; i < names.length; i++) {
console.log(names[i]);
}
Abstraction
# Loop hides complexity of iteration
def print_all(items):
for item in items:
print(item)
# Don't need to know how items are stored
print_all([1, 2, 3])
print_all("Hello") # Strings are iterable too!
Types of Loops
Loop Type Comparison
| Loop Type | When to Use | Example Use Case |
|---|---|---|
| For Loop | Known number of iterations | Processing array elements, counting |
| While Loop | Unknown iterations, condition-based | Reading until end of file, user input |
| Do-While | At least one execution needed | Menu systems, validation loops |
| For-Each | Iterating over collections | Processing each element in array/list |
For Loop
Basic Syntax
# Python for loop
for i in range(5): # 0, 1, 2, 3, 4
print(f"Iteration {i}")
// JavaScript for loop
for (let i = 0; i < 5; i++) {
console.log(`Iteration ${i}`);
}
// Java for loop
for (int i = 0; i < 5; i++) {
System.out.println("Iteration " + i);
}
// C for loop
for (int i = 0; i < 5; i++) {
printf("Iteration %d\n", i);
}
For Loop Components
// Three parts of a for loop
for (initialization; condition; increment) {
// loop body
}
// Example with explanation
for (let i = 0; // 1. Initialize counter (executed once)
i < 5; // 2. Condition (checked before each iteration)
i++) { // 3. Increment (executed after each iteration)
// 4. Loop body
}
For Loop Variations
# Python - range with start, stop, step for i in range(1, 10, 2): # 1, 3, 5, 7, 9 print(i) # Reverse order for i in range(10, 0, -1): # 10, 9, 8, ..., 1 print(i)
// JavaScript - multiple variables
for (let i = 0, j = 10; i < j; i++, j--) {
console.log(`i=${i}, j=${j}`);
}
// Omitting parts
let i = 0;
for (; i < 5; ) {
console.log(i);
i++;
}
Nested For Loops
# Multiplication table
for i in range(1, 11):
for j in range(1, 11):
print(f"{i} × {j} = {i*j}")
print() # Blank line between tables
// 2D array iteration
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
console.log(matrix[i][j]);
}
}
While Loop
Basic Syntax
# Python while loop
count = 0
while count < 5:
print(f"Count: {count}")
count += 1
// JavaScript while loop
let count = 0;
while (count < 5) {
console.log(`Count: ${count}`);
count++;
}
// Java while loop
int count = 0;
while (count < 5) {
System.out.println("Count: " + count);
count++;
}
While Loop Examples
# User input until valid
valid_input = False
while not valid_input:
user_input = input("Enter a number between 1 and 10: ")
if user_input.isdigit() and 1 <= int(user_input) <= 10:
valid_input = True
print(f"Valid input: {user_input}")
else:
print("Invalid input, try again")
// Reading until end of file
const fs = require('fs');
let data = fs.readFileSync('data.txt', 'utf8');
let lines = data.split('\n');
let index = 0;
while (index < lines.length) {
console.log(lines[index]);
index++;
}
Sentinel-Controlled Loops
# Sentinel value -1 to exit
total = 0
count = 0
while True:
num = int(input("Enter a number (-1 to quit): "))
if num == -1:
break
total += num
count += 1
if count > 0:
print(f"Average: {total / count}")
Do-While Loop
Syntax (Languages with Do-While)
// C do-while loop
int count = 0;
do {
printf("Count: %d\n", count);
count++;
} while (count < 5);
// JavaScript - using do-while
let count = 0;
do {
console.log(`Count: ${count}`);
count++;
} while (count < 5);
// Java do-while loop
int count = 0;
do {
System.out.println("Count: " + count);
count++;
} while (count < 5);
Emulating Do-While in Python
# Python doesn't have do-while, but can emulate
count = 0
while True:
print(f"Count: {count}")
count += 1
if not (count < 5):
break
When to Use Do-While
# Menu system - always execute at least once
def menu_system():
while True:
print("\n1. Option 1")
print("2. Option 2")
print("3. Exit")
choice = input("Choose: ")
if choice == "1":
print("Option 1 selected")
elif choice == "2":
print("Option 2 selected")
elif choice == "3":
break
else:
print("Invalid choice")
// C - do-while perfect for validation
int number;
do {
printf("Enter a positive number: ");
scanf("%d", &number);
} while (number <= 0);
For-Each / Enhanced For Loop
Python For-Each
# Python - iterate over sequence
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# With index using enumerate
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
# Over string characters
for char in "hello":
print(char)
# Over dictionary
person = {"name": "Alice", "age": 25, "city": "New York"}
for key, value in person.items():
print(f"{key}: {value}")
JavaScript For-Each
// JavaScript for...of (ES6)
const fruits = ["apple", "banana", "cherry"];
for (const fruit of fruits) {
console.log(fruit);
}
// for...in (for object properties)
const person = { name: "Alice", age: 25 };
for (const key in person) {
console.log(`${key}: ${person[key]}`);
}
// Array forEach method
fruits.forEach((fruit, index) => {
console.log(`${index}: ${fruit}`);
});
Java Enhanced For Loop
// Java for-each loop
String[] fruits = {"apple", "banana", "cherry"};
for (String fruit : fruits) {
System.out.println(fruit);
}
// With collections
List<String> list = Arrays.asList("apple", "banana", "cherry");
for (String fruit : list) {
System.out.println(fruit);
}
Loop Control Statements
Break Statement
# Python break - exit loop early for i in range(10): if i == 5: break print(i) # Prints 0,1,2,3,4
// JavaScript break
for (let i = 0; i < 10; i++) {
if (i === 5) break;
console.log(i);
}
Continue Statement
# Python continue - skip current iteration for i in range(10): if i % 2 == 0: continue print(i) # Prints 1,3,5,7,9
// JavaScript continue
for (let i = 0; i < 10; i++) {
if (i % 2 === 0) continue;
console.log(i);
}
Labeled Break and Continue
// JavaScript - breaking out of nested loops
outer: for (let i = 0; i < 5; i++) {
for (let j = 0; j < 5; j++) {
if (i === 2 && j === 2) {
break outer; // Breaks outer loop
}
console.log(`i=${i}, j=${j}`);
}
}
# Python - using else clause with loops
for i in range(5):
print(i)
else:
print("Loop completed normally") # Executes if no break
for i in range(5):
if i == 3:
break
print(i)
else:
print("This won't execute") # Skips because break occurred
Return in Loops
// JavaScript - return exits function and loop
function findFirstEven(numbers) {
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 === 0) {
return numbers[i]; // Exits loop AND function
}
}
return null; // No even found
}
Nested Loops
Basic Nested Loops
# Simple nested loops
for i in range(3):
for j in range(3):
print(f"({i},{j})", end=" ")
print()
# Output:
# (0,0) (0,1) (0,2)
# (1,0) (1,1) (1,2)
# (2,0) (2,1) (2,2)
Triangular Patterns
# Right triangle
for i in range(1, 6):
for j in range(i):
print("*", end="")
print()
# Output:
# *
# **
# ***
# ****
# *****
# Pyramid
rows = 5
for i in range(rows):
for j in range(rows - i - 1):
print(" ", end="")
for k in range(2 * i + 1):
print("*", end="")
print()
Matrix Operations
# Matrix multiplication
def matrix_multiply(A, B):
rows_A = len(A)
cols_A = len(A[0])
rows_B = len(B)
cols_B = len(B[0])
if cols_A != rows_B:
raise ValueError("Cannot multiply matrices")
result = [[0 for _ in range(cols_B)] for _ in range(rows_A)]
for i in range(rows_A):
for j in range(cols_B):
for k in range(cols_A):
result[i][j] += A[i][k] * B[k][j]
return result
# Example
A = [[1, 2], [3, 4]]
B = [[5, 6], [7, 8]]
result = matrix_multiply(A, B)
print(result) # [[19, 22], [43, 50]]
Infinite Loops
Creating Infinite Loops
# Python infinite loops
while True:
print("This runs forever") # Use break to exit
# Or
for i in range(1, 10**10): # Very large range
print(i)
// JavaScript infinite loops
while (true) {
console.log("Infinite");
}
for (;;) {
console.log("Also infinite");
}
Useful Infinite Loops
# Server listening loop def server(): while True: connection = accept_connection() if connection: handle_connection(connection) else: break # Game main loop def game_loop(): running = True while running: handle_input() update_game_state() render() # Break condition inside if game_over: running = False # Event loop def event_loop(): while True: event = get_next_event() if event.type == QUIT: break process_event(event)
Preventing Infinite Loops
# Always have an exit condition count = 0 while count < 100: # Make sure condition eventually becomes false count += 1 # Or use a timeout import time start_time = time.time() while time.time() - start_time < 60: # Run for 60 seconds max # Do work pass
Loop Performance
Performance Comparison
import time
# Inefficient loop
start = time.time()
result = 0
for i in range(1000000):
result += i
print(f"Time: {time.time() - start:.4f}s")
# More efficient - use built-in functions
start = time.time()
result = sum(range(1000000))
print(f"Time: {time.time() - start:.4f}s")
Optimizing Loops
# ❌ Inefficient - calculating length each iteration for i in range(len(my_list)): do_something(my_list[i]) # ✅ Efficient - cache length length = len(my_list) for i in range(length): do_something(my_list[i])
// ❌ Inefficient - DOM access in loop
for (let i = 0; i < 1000; i++) {
document.getElementById('element').innerHTML += i;
}
// ✅ Efficient - build string first
let html = '';
for (let i = 0; i < 1000; i++) {
html += i;
}
document.getElementById('element').innerHTML = html;
Loop Unrolling
// C - loop unrolling for performance
// Regular loop
for (int i = 0; i < 100; i++) {
process(i);
}
// Unrolled loop (process 4 at a time)
int i;
for (i = 0; i < 100 - 3; i += 4) {
process(i);
process(i+1);
process(i+2);
process(i+3);
}
// Handle remainder
for (; i < 100; i++) {
process(i);
}
Common Loop Patterns
Accumulator Pattern
# Sum all numbers
numbers = [1, 2, 3, 4, 5]
total = 0
for num in numbers:
total += num
print(f"Sum: {total}")
# Product of numbers
product = 1
for num in numbers:
product *= num
print(f"Product: {product}")
Filter Pattern
# Filter even numbers
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = []
for num in numbers:
if num % 2 == 0:
evens.append(num)
print(f"Evens: {evens}")
# Filter with condition
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
primes = [num for num in range(2, 50) if is_prime(num)]
print(f"Primes: {primes}")
Map Pattern
# Transform each element
numbers = [1, 2, 3, 4, 5]
squares = []
for num in numbers:
squares.append(num ** 2)
print(f"Squares: {squares}")
# With list comprehension
squares = [num ** 2 for num in numbers]
Search Pattern
# Linear search def find_index(arr, target): for i, value in enumerate(arr): if value == target: return i return -1 # Binary search (requires sorted array) def binary_search(arr, target): left, right = 0, len(arr) - 1 while left <= right: mid = (left + right) // 2 if arr[mid] == target: return mid elif arr[mid] < target: left = mid + 1 else: right = mid - 1 return -1
Reduction Pattern
# Find maximum
numbers = [3, 7, 2, 9, 1, 5]
max_value = numbers[0]
for num in numbers[1:]:
if num > max_value:
max_value = num
print(f"Max: {max_value}")
# Find minimum
min_value = numbers[0]
for num in numbers[1:]:
if num < min_value:
min_value = num
print(f"Min: {min_value}")
Zip Pattern
# Iterate over multiple lists simultaneously
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
cities = ["New York", "London", "Paris"]
for name, age, city in zip(names, ages, cities):
print(f"{name} is {age} years old from {city}")
Language-Specific Examples
Python
# Python - versatile loops
# For loop with range
for i in range(10):
print(i)
# For loop with enumerate
colors = ['red', 'green', 'blue']
for idx, color in enumerate(colors):
print(f"{idx}: {color}")
# While loop with else
count = 0
while count < 3:
print(count)
count += 1
else:
print("Loop completed")
# List comprehension (functional loop)
squares = [x**2 for x in range(10)]
# Generator expression (lazy evaluation)
squares_gen = (x**2 for x in range(10))
JavaScript
// JavaScript - modern loops
// Traditional for loop
for (let i = 0; i < 5; i++) {
console.log(i);
}
// for...of (values)
const arr = [1, 2, 3];
for (const value of arr) {
console.log(value);
}
// for...in (keys)
const obj = { a: 1, b: 2, c: 3 };
for (const key in obj) {
console.log(`${key}: ${obj[key]}`);
}
// forEach (arrays)
arr.forEach((value, index) => {
console.log(`${index}: ${value}`);
});
// map (creates new array)
const doubled = arr.map(x => x * 2);
// filter (creates new array)
const evens = arr.filter(x => x % 2 === 0);
Java
// Java - traditional loops
// For loop
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
// Enhanced for loop
String[] names = {"Alice", "Bob", "Charlie"};
for (String name : names) {
System.out.println(name);
}
// While loop
int count = 0;
while (count < 5) {
System.out.println(count);
count++;
}
// Do-while
int num = 0;
do {
System.out.println(num);
num++;
} while (num < 5);
// Java 8+ streams
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * 2)
.forEach(System.out::println);
C++
// C++ - loops
#include <iostream>
#include <vector>
int main() {
// Traditional for loop
for (int i = 0; i < 5; i++) {
std::cout << i << std::endl;
}
// Range-based for loop (C++11)
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (int n : numbers) {
std::cout << n << std::endl;
}
// While loop
int count = 0;
while (count < 5) {
std::cout << count << std::endl;
count++;
}
// Do-while
int num = 0;
do {
std::cout << num << std::endl;
num++;
} while (num < 5);
return 0;
}
Rust
// Rust - loops
fn main() {
// For loop over range
for i in 0..5 {
println!("{}", i);
}
// For loop with inclusive range
for i in 0..=5 {
println!("{}", i);
}
// While loop
let mut count = 0;
while count < 5 {
println!("{}", count);
count += 1;
}
// Loop (infinite) with break
let mut num = 0;
loop {
if num >= 5 {
break;
}
println!("{}", num);
num += 1;
}
// Iterating over collections
let numbers = vec![1, 2, 3, 4, 5];
for num in &numbers {
println!("{}", num);
}
// With index
for (i, num) in numbers.iter().enumerate() {
println!("{}: {}", i, num);
}
}
Best Practices
Loop Design Principles
# 1. Use meaningful variable names for i in range(10): # i is okay for simple counters pass for student in students: # Better for collections print(student) # 2. Keep loops simple # ❌ Complex logic inside loop for i in range(100): if i % 2 == 0 and i > 50 and i < 80: # Complex condition do_something(i) # ✅ Extract logic to functions def should_process(i): return i % 2 == 0 and 50 < i < 80 for i in range(100): if should_process(i): do_something(i)
Avoid Common Anti-Patterns
# ❌ Modifying list while iterating
numbers = [1, 2, 3, 4, 5]
for num in numbers:
if num % 2 == 0:
numbers.remove(num) # Dangerous!
# ✅ Create new list
numbers = [1, 2, 3, 4, 5]
evens = [num for num in numbers if num % 2 == 0]
# ❌ Using index when not needed
for i in range(len(my_list)):
print(my_list[i])
# ✅ Use direct iteration
for item in my_list:
print(item)
# ✅ Or enumerate if index needed
for i, item in enumerate(my_list):
print(f"{i}: {item}")
Loop Invariants
# Maintain loop invariants for correctness def binary_search(arr, target): left = 0 right = len(arr) - 1 # Invariant: target is in [left, right] if it exists while left <= right: mid = (left + right) // 2 if arr[mid] == target: return mid elif arr[mid] < target: left = mid + 1 # Invariant maintained else: right = mid - 1 # Invariant maintained return -1 # Target not found
Performance Optimization
# 1. Move invariant calculations outside loop # ❌ for i in range(1000): x = len(my_list) # Same each time process(i, x) # ✅ length = len(my_list) for i in range(1000): process(i, length) # 2. Use list comprehensions for simple transformations # ❌ result = [] for x in range(1000): result.append(x * 2) # ✅ result = [x * 2 for x in range(1000)] # 3. Use generators for large datasets # ❌ Uses memory squares = [x**2 for x in range(10000000)] # ✅ Uses less memory squares = (x**2 for x in range(10000000))
Common Pitfalls
Off-by-One Errors
# ❌ Off-by-one - misses last element numbers = [1, 2, 3, 4, 5] for i in range(len(numbers) - 1): print(numbers[i]) # Prints only 1,2,3,4 # ✅ Correct for i in range(len(numbers)): print(numbers[i]) # Better - direct iteration for num in numbers: print(num)
Infinite Loops
# ❌ Infinite loop count = 0 while count < 10: print(count) # forgot to increment count! # ✅ Always update loop condition while count < 10: print(count) count += 1
Loop Variable Shadowing
# ❌ Variable name conflict i = 10 for i in range(5): # Shadows outer i pass print(i) # 4, not 10! # ✅ Use different names outer_counter = 10 for i in range(5): pass print(outer_counter) # 10
Nested Loop Complexity
# ❌ O(n²) complexity for i in range(len(arr)): for j in range(len(arr)): if i != j: compare(arr[i], arr[j]) # ✅ Consider if you can reduce complexity # Use sets, dictionaries, or sort first
Conclusion
Loops are fundamental constructs that enable efficient repetition in programming.
Key Takeaways
- Types: For loops (known iterations), While loops (condition-based), Do-while (always runs once), For-each (collections)
- Components: Initialization, condition, increment, body
- Control: Break (exit loop), Continue (skip iteration), Return (exit function)
- Nested Loops: Loops inside loops (matrix operations, patterns)
- Performance: Choose right loop type, optimize inner loops, move invariant code
- Patterns: Accumulator, filter, map, search, reduction, zip
- Best Practices: Use meaningful names, keep loops simple, avoid modifying collections during iteration
Loop Selection Guide
| Scenario | Recommended Loop |
|---|---|
| Known number of iterations | For loop |
| Unknown iterations, condition-based | While loop |
| At least one iteration needed | Do-while (or while True with break) |
| Iterating over collection | For-each / Enhanced for |
| Complex exit conditions | While True with break |
| Index needed with collection | For loop with index or enumerate |
Performance Tips
- Pre-calculate loop-invariant expressions
- Avoid function calls inside tight loops
- Use built-in functions (sum, max, min) when possible
- Consider vectorized operations (NumPy, array operations)
- Move I/O operations outside loops when possible
- Use appropriate data structures (sets for membership testing)
Final Thought
Loops are like assembly lines in manufacturing - they automate repetitive tasks efficiently. Mastering loops is essential for writing effective, efficient, and elegant code!