Skip to content

S1Q3 · Remove Elements at Two Given Indices

⚡ Quick Reference

Function: remove_elements_at_two_indices(l: list, i1: int, i2: int) -> None

Core idea: always delete the larger index first - removing a smaller index shifts later elements and invalidates the larger index.

def remove_elements_at_two_indices(l: list, i1: int, i2: int):
    first, second = (i1, i2) if i1 > i2 else (i2, i1)
    del l[first]
    del l[second]

Key rules: - Modifies l in-place - returns None - Delete the larger index first to avoid index shift - del l[i] removes element at index i in-place


Problem Statement

Problem

Write a function remove_elements_at_two_indices(l, i1, i2) that removes the elements at indices i1 and i2 from l in-place. Returns None.

Example:

Input
l=[1,2,3,4,5,6,7], i1=5, i2=1
After call
[1, 3, 4, 5, 7]

The index-shift problem

If you delete i2=1 first:

[1, 2, 3, 4, 5, 6, 7]  → del l[1] → [1, 3, 4, 5, 6, 7]
Now index 5 points to 7 instead of 6 - wrong element deleted.

If you delete i1=5 first (larger):

[1, 2, 3, 4, 5, 6, 7]  → del l[5] → [1, 2, 3, 4, 5, 7]
Index 1 still points to 2 - correct.
[1, 2, 3, 4, 5, 7]     → del l[1] → [1, 3, 4, 5, 7] 

Always delete larger index first

Deleting an element shifts all elements to its right one position left. If you delete the smaller index first, the larger index is now off by one. Deleting the larger index first avoids this entirely.


Solution approaches

def remove_elements_at_two_indices(l: list, i1: int, i2: int):
    for i in sorted([i1, i2], reverse=True):
        del l[i]

Sort both indices in descending order, delete in that order. Scales if ever extended to more than two indices.

def remove_elements_at_two_indices(l: list, i1: int, i2: int):
    if i1 > i2:
        del l[i1]
        del l[i2]
    else:
        del l[i2]
        del l[i1]

Explicit ordering - always delete the larger first.

def remove_elements_at_two_indices(l: list, i1: int, i2: int):
    del l[max(i1, i2)]
    del l[min(i1, i2)]

max and min pick the right order in one expression each. Clean and readable.

def remove_elements_at_two_indices(l: list, i1: int, i2: int):
    to_remove = {i1, i2}
    kept = [v for i, v in enumerate(l) if i not in to_remove]
    l[:] = kept

Build the filtered list, then use slice assignment l[:] = kept to modify l in-place. The set lookup is O(1). Works correctly regardless of index order.

def remove_elements_at_two_indices(l: list, i1: int, i2: int):
    list(map(lambda i: l.__delitem__(i),
             sorted([i1, i2], reverse=True)))

map applies del via list.__delitem__ to each index in descending order. Functional style - though the explicit sorted loop is cleaner here.


Key takeaways

01

Delete larger index first

Removing an element shifts all later indices left by 1. Always delete in descending index order to avoid invalidating the remaining index.

02

del vs pop()

del l[i] and l.pop(i) both remove by index in-place. del discards the value; pop(i) returns it. Use del when you don't need the removed value.

03

l[:] = new_list for in-place reassignment

l[:] = filtered replaces the contents of l in-place - the original list object is modified. l = filtered would just rebind the local variable and not affect the caller.