The effects of the three different methods to remove an element from a list:
remove removes the first matching value, not a specific index:
>>> a = [0, 2, 3, 2]
>>> a.remove(2)
>>> a
[0, 3, 2]
del removes the item at a specific index:
>>> a = [9, 8, 7, 6]
>>> del a[1]
>>> a
[9, 7, 6]
and pop removes the item at a specific index and returns it.
>>> a = [4, 3, 5]
>>> a.pop(1)
3
>>> a
[4, 5]
Their error modes are different too:
>>> a = [4, 5, 6]
>>> a.remove(7)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
>>> del a[7]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> a.pop(7)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: pop index out of range
Answer from Martijn Pieters on Stack OverflowThis feels like one of those python weird things. I am interested in explanations.
If I have a list=[1,2,3,4] and I do list.pop() the result is list=[1,2,3].
Perfect, just what I wanted.
However, if I am not careful and instead do list.pop--note there are no parentheses this time--I get no syntax error or warning and nothing happens, leading me to a strange debug session.
In the repl, if I do l.pop it just identifies it as a built-in method of list object at 0xwhatever. That's useful, but why is there not at least a runtime warning when I make this mistake in my code?
Can someone explain me what the difference between pop and remove is that makes sense? Why would you use pop over remove or vice versa?
Thanks!
The effects of the three different methods to remove an element from a list:
remove removes the first matching value, not a specific index:
>>> a = [0, 2, 3, 2]
>>> a.remove(2)
>>> a
[0, 3, 2]
del removes the item at a specific index:
>>> a = [9, 8, 7, 6]
>>> del a[1]
>>> a
[9, 7, 6]
and pop removes the item at a specific index and returns it.
>>> a = [4, 3, 5]
>>> a.pop(1)
3
>>> a
[4, 5]
Their error modes are different too:
>>> a = [4, 5, 6]
>>> a.remove(7)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
>>> del a[7]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> a.pop(7)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: pop index out of range
Use del to remove an element by index, pop() to remove it by index if you need the returned value, and remove() to delete an element by value. The last requires searching the list, and raises ValueError if no such value occurs in the list.
When deleting index i from a list of n elements, the computational complexities of these methods are
del O(n - i)
pop O(n - i)
remove O(n)
Are your lists large? If so, use ifilter from itertools to filter out elements that you don't want lazily (with no up front cost).
Lists not so large? Just use a list comprehension:
newlist = [x for x in oldlist if x not in ['a', 'c'] ]
This will create a new copy of the list. This is not generally an issue for efficiency unless you really care about memory consumption.
As a happy medium of syntax convenience and laziness ( = efficiency for large lists), you can construct a generator rather than a list by using ( ) instead of [ ]:
interestingelts = (x for x in oldlist if x not in ['a', 'c'])
After this, you can iterate over interestingelts, but you can't index into it:
for y in interestingelts: # ok
print y
print interestingelts[0] # not ok: generator allows sequential access only
You want a list comprehension:
L = [c for c in L if c not in ['a', 'c']]
Or, if you really don't want to create a copy, go backwards:
for i in reversed(range(len(L))):
if L[i] in ['a', 'c']:
L.pop(i) # del L[i] is more efficient
Thanks to ncoghlan for reversed() & phooji for del L[i] suggestions. (I decided to leave it as L.pop(i), since that's how the question was initially formulated.)
Also, as J.S. Sebastian correctly points out, going backwards is space efficient but time inefficient; most of the time a list comprehension or generator (L = (...) instead of L = [...]) is best.
Edit:
Ok, so since people seem to want something less ridiculously slow than the reversed method above (I can't imagine why... :) here's an order-preserving, in-place filter that should differ in speed from a list comprehension only by a constant. (This is akin to what I'd do if I wanted to filter a string in c.)
write_i = 0
for read_i in range(len(L)):
L[write_i] = L[read_i]
if L[read_i] not in ['a', 'c']:
write_i += 1
del L[write_i:]
print L
# output: ['b', 'd']
listoflists[1].pop(0)
listoflists[1] equals list2
so
listoflists[1].pop(0) equals list2.pop(0)
the correct way to pop 2d arrays is like this
list1=[1,2]
list2=[3,4]
listoflists=[list1, list2]
print listoflists
listoflists[0].pop(0)//correct way to pop
print listoflists
here is another post similar to yours on poping 2d lists that also might be of use.
From a performance point of view:
mylist = mylist[2:-2]anddel mylist[:2];del mylist[-2:]are equivalent- they are around 3 times faster than the first solution
for _ in range(2): mylist.pop(0); mylist.pop()
Code
iterations = 1000000
print timeit.timeit('''mylist=range(9)\nfor _ in range(2): mylist.pop(0); mylist.pop()''', number=iterations)/iterations
print timeit.timeit('''mylist=range(9)\nmylist = mylist[2:-2]''', number=iterations)/iterations
print timeit.timeit('''mylist=range(9)\ndel mylist[:2];del mylist[-2:]''', number=iterations)/iterations
output
1.07710313797e-06
3.44465017319e-07
3.49956989288e-07
You could slice out a new list, keeping the old list as is:
mylist=['a','b','c','d','e','f','g','h','i']
newlist = mylist[2:-2]
newlist now returns:
['c', 'd', 'e', 'f', 'g']
You can overwrite the reference to the old list too:
mylist = mylist[2:-2]
Both of the above approaches will use more memory than the below.
What you're attempting to do yourself is memory friendly, with the downside that it mutates your old list, but popleft is not available for lists in Python, it's a method of the collections.deque object.
This works well in Python 3:
for x in range(2):
mylist.pop(0)
mylist.pop()
In Python 2, use xrange and pop only:
for _ in xrange(2):
mylist.pop(0)
mylist.pop()
Fastest way to delete as Martijn suggests, (this only deletes the list's reference to the items, not necessarily the items themselves):
del mylist[:2]
del mylist[-2:]
list.pop() takes the index of an element to remove, not the item to remove. Try using list.remove() instead.
As the Python documentation says:
array.pop([i])
Removes the item with the index i from the array and returns it. The optional argument defaults to -1, so that by default the last item is removed and returned.
You need to mention the index number for using array.pop().
You can solve as below:
list_example = [1, 2, 3, 4, 5] # List example
removed = list_example.pop(3) # remove by index
list_example.insert(2, removed) # Adding the element removed in the position required
The result would be:
[1, 2, 4, 3, 5]
The value is returned by the .pop() method. If you want the value, you could do (where index is the index of the item you want to remove):
index = 3
lst = [1, 2, 3, 4, 5]
value = lst.pop(index)
and if you wanted to insert it back into the list at a different location, you could do:
new_index = 1
old_index = 3
lst = [1, 2, 3, 4, 5]
lst.insert(new_index, lst.pop(old_index))