2

Say I have a 2d list like this:

list = [[1, 2, 3], ["a", 5, 6], [7, 8, 9], [10, 11, 12]]

and I want to delete a list that starts with a. Here is what I tried:

for i in range(0, len(list)):
     if list[i][0] == "a":
          list.pop(i)

Here, I am trying to delete a list that starts with a. However, it gives me an error saying

IndexError: list index out of range

I am not sure what the problem is here. It's weird because when I try print(list[i]), it prints the matching line, which is `["a", 2, 3].

I am expecting list = [[1, 2, 3], [7, 8, 9], [10, 11, 12]] as my final list.

Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
Isaac
  • 273
  • 3
  • 19

5 Answers5

8

Use a list comprehension:

>>> l = [[1, 2, 3], ["a", 5, 6], [7, 8, 9], [10, 11, 12]]
>>> new_l = [sublist for sublist in l if sublist[0] != 'a']
>>> new_l
[[1, 2, 3], [7, 8, 9], [10, 11, 12]]

In general, it is not a good idea to name your variables after inbuilts (list) since you will shadow those inbuilts.

Also, as others have noted, your original problem was mutating the list while iterating over it.

gmds
  • 19,325
  • 4
  • 32
  • 58
1

Use a list comprehension:

[x for x in my_list if x[0] != 'a']
Ramy M. Mousa
  • 5,727
  • 3
  • 34
  • 45
Russ Brown
  • 171
  • 6
1

What's happening is that your list length gets shorter as you delete items from it. It will still try to loop at i = 3.

You could use a while loop instead since it checks every time. Also since you're not using the popped value, use del

list = [[1, 2, 3], ["a", 5, 6], [7, 8, 9], [10, 11, 12]]
i = 0
while i < len(list):
    if list[i][0] == "a":
        del list[i]
    else:
        i += 1

Related: Difference between del, remove and pop on lists

CloudEmber
  • 99
  • 4
1

You can also use filter for this!

li = [[1, 2, 3], ["a", 5, 6], [7, 8, 9], [10, 11, 12]]

#Filter on first element not being equal to a
res = filter(lambda x: x[0] != 'a', li)

#Print the result
print(list(res))
#[[1, 2, 3], [7, 8, 9], [10, 11, 12]]
Devesh Kumar Singh
  • 20,259
  • 5
  • 21
  • 40
0

How about an approach using filter? Also I renamed your list to l so you don't overwrite the built-in data type.

from operator import itemgetter

f = itemgetter(0)

def test(sublist):
    return f(sublist) != 'a'

list(filter(test, l))

[[1, 2, 3], [7, 8, 9], [10, 11, 12]]
gold_cy
  • 13,648
  • 3
  • 23
  • 45