Arrays & Lists

Master linear data structures for efficient data storage

📊 What are Arrays & Lists?

Arrays and Lists are linear data structures that store elements in a sequential order. Think of them as containers where you can store multiple items and access them by their position!


# Creating arrays/lists in Python
numbers = [1, 2, 3, 4, 5]  # List
grades = [95, 87, 92, 78, 88]  # Another list

# Accessing elements by index
print(numbers[0])    # First element: 1
print(numbers[-1])   # Last element: 5
print(len(numbers))  # Length: 5
                                    
O(1)
Access
Sequential
Storage
Dynamic
Size

Arrays vs Lists Characteristics

📏

Arrays

Fixed size, same data type

Fixed Size Homogeneous
🔄

Dynamic Lists

Resizable, mixed data types

Dynamic Flexible

Fast Access

O(1) random access by index

Indexing Direct
🔍

Sequential

Elements stored in contiguous memory

Cache-friendly Memory

Lesson 1: Creating Arrays and Lists

Let's start by creating different types of arrays and lists:

Array/List Creation Methods

🔹Creating lists with different data types


# Integer list
numbers = [1, 2, 3, 4, 5]
print("Numbers:", numbers)

# String list
fruits = ["apple", "banana", "orange"]
print("Fruits:", fruits)

# Mixed data types
mixed = [1, "hello", 3.14, True]
print("Mixed:", mixed)

🔹Creating empty lists and adding elements


# Empty list
empty_list = []
print("Empty list:", empty_list)

# Adding elements
empty_list.append(10)
empty_list.append(20)
print("After adding:", empty_list)

🔹Creating lists with specific patterns


# List with repeated values
zeros = [0] * 5
print("Zeros:", zeros)  # [0, 0, 0, 0, 0]

# List with range
range_list = list(range(1, 6))
print("Range:", range_list)  # [1, 2, 3, 4, 5]

# List comprehension
squares = [x**2 for x in range(1, 6)]
print("Squares:", squares)  # [1, 4, 9, 16, 25]

🔹Using NumPy arrays (for numerical computing)


import numpy as np

# NumPy array (fixed type, more efficient)
np_array = np.array([1, 2, 3, 4, 5])
print("NumPy array:", np_array)
print("Array type:", np_array.dtype)

# 2D array
matrix = np.array([[1, 2, 3], [4, 5, 6]])
print("2D array:\n", matrix)

Lesson 2: Accessing and Indexing

Learn how to access elements using indices and slicing:

Array Indexing Example: [10, 20, 30, 40, 50]

Value 10 20 30 40 50
Positive Index 0 1 2 3 4
Negative Index -5 -4 -3 -2 -1
Indexing and Slicing
numbers = [10, 20, 30, 40, 50]

# Positive indexing
print("First element:", numbers[0])    # 10
print("Second element:", numbers[1])   # 20
print("Last element:", numbers[4])     # 50

# Negative indexing
print("Last element:", numbers[-1])    # 50
print("Second last:", numbers[-2])     # 40

# Slicing
print("First 3:", numbers[0:3])        # [10, 20, 30]
print("Last 2:", numbers[-2:])         # [40, 50]
print("Every other:", numbers[::2])    # [10, 30, 50]
print("Reverse:", numbers[::-1])       # [50, 40, 30, 20, 10]

Lesson 3: Adding, Removing, and Modifying Elements

Learn how to modify lists dynamically:

List Modification Operations

🔹Adding elements


fruits = ["apple", "banana"]
print("Original:", fruits)

# Add to end
fruits.append("orange")
print("After append:", fruits)

# Add at specific position
fruits.insert(1, "grape")
print("After insert:", fruits)

# Add multiple elements
fruits.extend(["mango", "kiwi"])
print("After extend:", fruits)

🔹Removing elements


numbers = [1, 2, 3, 4, 5, 3]
print("Original:", numbers)

# Remove by value (first occurrence)
numbers.remove(3)
print("After remove(3):", numbers)

# Remove by index
removed = numbers.pop(2)
print(f"Removed {removed}, list:", numbers)

# Remove last element
last = numbers.pop()
print(f"Removed {last}, list:", numbers)

# Clear all elements
numbers.clear()
print("After clear:", numbers)

🔹Modifying elements


grades = [85, 90, 78, 92, 88]
print("Original grades:", grades)

# Modify single element
grades[2] = 82
print("After modification:", grades)

# Modify multiple elements
grades[1:3] = [95, 87]
print("After slice modification:", grades)

# Modify with conditions
for i in range(len(grades)):
    if grades[i] < 85:
        grades[i] += 5  # Bonus points
print("After bonus:", grades)

Lesson 4: Searching Elements

Different ways to find elements in arrays and lists:

Search Operations
numbers = [10, 25, 30, 45, 50, 25]

# Check if element exists
if 25 in numbers:
    print("25 is in the list")

# Find index of element
try:
    index = numbers.index(25)
    print(f"First occurrence of 25 at index: {index}")
except ValueError:
    print("Element not found")

# Count occurrences
count = numbers.count(25)
print(f"25 appears {count} times")

# Linear search implementation
def linear_search(arr, target):
    for i in range(len(arr)):
        if arr[i] == target:
            return i
    return -1

result = linear_search(numbers, 45)
print(f"45 found at index: {result}")

# Find all occurrences
def find_all_occurrences(arr, target):
    indices = []
    for i in range(len(arr)):
        if arr[i] == target:
            indices.append(i)
    return indices

all_25 = find_all_occurrences(numbers, 25)
print(f"All occurrences of 25: {all_25}")

Lesson 5: Sorting Arrays and Lists

Learn different ways to sort your data:

Sorting Operations
numbers = [64, 34, 25, 12, 22, 11, 90]
print("Original:", numbers)

# Built-in sort (modifies original list)
numbers_copy = numbers.copy()
numbers_copy.sort()
print("Sorted (ascending):", numbers_copy)

# Sort in descending order
numbers_copy.sort(reverse=True)
print("Sorted (descending):", numbers_copy)

# Using sorted() function (returns new list)
sorted_numbers = sorted(numbers)
print("Original unchanged:", numbers)
print("New sorted list:", sorted_numbers)

# Sorting strings
fruits = ["banana", "apple", "cherry", "date"]
print("Original fruits:", fruits)
fruits.sort()
print("Sorted fruits:", fruits)

# Custom sorting with key function
students = [("Alice", 85), ("Bob", 90), ("Charlie", 78)]
print("Original students:", students)

# Sort by grade (second element)
students.sort(key=lambda x: x[1])
print("Sorted by grade:", students)

# Sort by name length
fruits.sort(key=len)
print("Sorted by length:", fruits)

Common Array/List Operations

Access Operations

  • arr[i] - Get element at index
  • arr[i:j] - Slice elements
  • len(arr) - Get length
  • arr[-1] - Last element

Modification Operations

  • append() - Add to end
  • insert() - Add at position
  • remove() - Remove by value
  • pop() - Remove by index

Search Operations

  • in - Check existence
  • index() - Find position
  • count() - Count occurrences
  • min()/max() - Find extremes

Utility Operations

  • sort() - Sort in place
  • reverse() - Reverse order
  • copy() - Create copy
  • extend() - Add multiple

🧠 Test Your Knowledge

What is the time complexity of accessing an element by index in an array?

Which method adds an element to the end of a list?

What does arr[-1] return?