python - Issue with reversing list using list.pop() - Stack Overflow
python - How do I remove the first item from a list? - Stack Overflow
I was surprised at how slow list.pop() is! And list.remove() is even many times slower
How to reverse order to pop out Python 3.6.4 - Stack Overflow
Videos
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!
How about a simple reversal of string.
>>> x = 'abcd'
>>> x[::-1]
'dcba'
>>>
On your code:
Never mutate the list on which you are iterating with. It can cause subtle errors.
>>> strList = [1, 2, 3, 4, 5]
>>> reverseCharList = []
>>> for someChar in strList:
... print strList
... reverseCharList.append(strList.pop())
... print strList
...
[1, 2, 3, 4, 5] <-- Iteration 1
[1, 2, 3, 4]
[1, 2, 3, 4] <-- Iteration 2
[1, 2, 3]
[1, 2, 3] <-- Iteration 3
[1, 2]
See the following. Since you are using iterator (for .. in ..). You can see the iterator details directly and how mutating the list messes up with iterator.
>>> strList = [1, 2, 3, 4, 5]
>>> k = strList.__iter__()
>>> k.next()
1
>>> k.__length_hint__() <--- Still 4 to go
4
>>> strList.pop() <---- You pop an element
5
>>> k.__length_hint__() <----- Now only 3 to go
3
>>>
>>> k.next()
2
>>> k.__length_hint__()
2
for someChar in strList:
reverseCharList.append(strList.pop())
Is essentially the same as:
i = 0
while i < len(strList):
reverseCharList.append(strList.pop())
i += 1
First iteration i is 0, len(strList) is 4, and you pop+append 'd'.
Second iteration i is 1, len(strList) is 3, and you pop+append 'c'.
Third iteration i is 2, len(strList) is 2, so the loop condition fails and you're done.
(This is really done with an iterator on the list, not a local variable 'i'. I've shown it this way for clarity.)
If you want to manipulate the sequence you're iterating over it's generally better to use a while loop. eg:
while strList:
reverseCharList.append(strList.pop())
You can find a short collection of useful list functions here.
list.pop(index)
>>> l = ['a', 'b', 'c', 'd']
>>> l.pop(0)
'a'
>>> l
['b', 'c', 'd']
>>>
del list[index]
>>> l = ['a', 'b', 'c', 'd']
>>> del l[0]
>>> l
['b', 'c', 'd']
>>>
These both modify your original list.
Others have suggested using slicing:
- Copies the list
- Can return a subset
Also, if you are performing many pop(0), you should look at collections.deque
from collections import deque
>>> l = deque(['a', 'b', 'c', 'd'])
>>> l.popleft()
'a'
>>> l
deque(['b', 'c', 'd'])
- Provides higher performance popping from left end of the list
Slicing:
x = [0,1,2,3,4]
x = x[1:]
Which would actually return a subset of the original but not modify it.
I know there is a list.clear(), I'm just sharing that I didn't expect that using list.pop() and list.remove() specifically could slow down the program that much.
li = list(range(500000))
Creating a list is quick.
So we are going to test out pop/remove specific values. For the purpose of this "benchmark", we are going to remove all elements from the list:
while (li):
li.pop(0)
It took 74.735 seconds to pop all the elements! It's ridiculously long.
I KNOW it would have been much faster if I even had used li.pop() without the index or maybe used filter function, list comprehension with conditional or whatever
But that's what I'm trying to show, how slow it is to remove certain list items specifically using pop and remove methods.
And li.remove(), which always requires a specified value to remove, is even worse than pop!
for num in li:
li.remove(num)This one took me 303.268 seconds to complete. How crazy it is.
I've been having fun with abstract data structures. Implemented linked lists and a queues running on linked lists.
And for the sake of interest, I decided to compare the performance of the queue based on the linked list and the usual python list. And I was surprised. When my linked list Queue dequeued 500.000 elements in 0.5 seconds, while python list Queue was doing it in 75 seconds.
Although it's generally not a good pattern to use a dictionary as an ordered data type, you can do what you want like this:
my_dictionary.pop(next(iter(my_dictionary.keys())))
.popitem() doesn't take parameters, but .pop() does take a specific key to pop.
Even if dicts happen to be ordered in CPython 3.6+, they're the not right data structure if you need this sort of thing. I'd recommend using a list of 2-tuples instead.
If you don't want to do that, you can, as a hack, find the "first" key, then pop the value:
next_key = next(iter(my_dictionary))
next_value = my_dictionary.pop(next_key)
This may fail on other Python implementations than CPython.
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)
I've been strugling with a program implementation for some time now, and I just noticed a very wierd behavior of the pop method (pop is in my file, and del, as an alternative, returned the same result). Here is a minimun reproductible example:
words = (5*'Loren ipsun ').split()
print(words,'\n')
for i in range(10):
words.pop(i)
print(words)This is the console output:
['Loren', 'ipsun', 'Loren', 'ipsun', 'Loren', 'ipsun', 'Loren', 'ipsun', 'Loren', 'ipsun'] ['ipsun', 'Loren', 'ipsun', 'Loren', 'ipsun', 'Loren', 'ipsun', 'Loren', 'ipsun'] ['ipsun', 'ipsun', 'Loren', 'ipsun', 'Loren', 'ipsun', 'Loren', 'ipsun'] ['ipsun', 'ipsun', 'ipsun', 'Loren', 'ipsun', 'Loren', 'ipsun'] ['ipsun', 'ipsun', 'ipsun', 'ipsun', 'Loren', 'ipsun'] ['ipsun', 'ipsun', 'ipsun', 'ipsun', 'ipsun'] Traceback (most recent call last): IndexError: pop index out of range
Could someone explain to me why just Loren words are being erased?
[Edit] Solution:
words = (5*'Loren ipsun ').split()
print(words,'\n')
for i in range(10):
words.pop(0)
print(words)The first test isn't surprising; three elements are removed off the end.
The second test is a bit surprising. Only two elements are removed. Why?
List iteration in Python essentially consists of an incrementing index into the list. When you delete an element you shift all the elements on the right over. This may cause the index to point to a different element.
Illustratively:
start of loop
[0,0,0,1,2,3,4,5,6]
^ <-- position of index
delete first element (since current element = 0)
[0,0,1,2,3,4,5,6]
^
next iteration
[0,0,1,2,3,4,5,6]
^
delete first element (since current element = 0)
[0,1,2,3,4,5,6]
^
and from now on no zeros are encountered, so no more elements are deleted.
To avoid confusion in the future, try not to modify lists while you're iterating over them. While Python won't complain (unlike dictionaries, which cannot be modified during iteration), it will result in weird and usually counterintuitive situations like this one.
since in list or Stack works in last in first out[LIFO] so pop() is used it removes last element in your list
where as pop(0) means it removes the element in the index that is first element of the list
as per the Docs
list.pop([i]):
Remove the item at the given position in the list, and return it. If no index is specified, a.pop() removes and returns the last item in the list. (The square brackets around the i in the method signature denote that the parameter is optional, not that you should type square brackets at that position. You will see this notation frequently in the Python Library Reference.)