from typing import List

# Looping over lists

# Different ways that we can iterate through a list

# 1. Iterating over the elements of the list
courses = ['csc120', 'csc148', 'csc165']
for course in courses:
    print(course)
    #print(courses[course]) # wrong

print(course) # the last course from our previous loop, 'csc165'

# 2. Iterating over the indices
courses = ['csc120', 'csc148', 'csc165']
for i in range(len(courses)):
    print(courses[i])

# 3. Iterating using a while loop
# But often it's less ideal because there are more
# places to make mistakes

index = 0
while index < len(courses):
    print(courses[index])
    index = index + 1
    
    
# Functions with list looping

# For loop over the elements
def double_elements(L: List[int]) -> List[int]:
    """Return a new list with the elements of L doubled.
    
    Do not change/mutate L. (the argument to this function
    should not have its elements changed - only a new list
    should be returned)
    
    >>> double_elements([1,2,3])
    [2,4,6]
    """
    doubles = []
    # iterating over the elements directly - no indexes needed
    for num in L:
        doubles.append(num * 2)
    return doubles

# For loop over the indices:
def replace_with_double(L: List[int]) -> None:
    """Modify L so that each element is doubled.
    
    >>> nums = [1, 2, 3]
    >>> replace_with_double(nums)
    >>> nums
    [2, 4, 6]
    """
    # wrong: can't mutate numbers (or strings)
    #for num in L:
        #num = num * 2
    
    # must iterate over the indices    
    for i in range(len(L)):
        # we can change list elements in place by indexing:
        L[i] = L[i] * 2 
        
# When you want to modify a list with immutable elements (like numbers or strings), you have to iterate over the indices.


nums = [1, 2, 3]
replace_with_double(nums)
print(nums)
