You could just slice the list:
mainlist = [5,4,3,2,1]
n = 3
mainlist, mylist = mainlist[:n], mainlist[n:]
Keep in mind that for slicing, the first index is inclusive, while the second is exclusive, so mainlist wouldn't contain index 3 but mylist would.
Answer from ccl on Stack OverflowYou could just slice the list:
mainlist = [5,4,3,2,1]
n = 3
mainlist, mylist = mainlist[:n], mainlist[n:]
Keep in mind that for slicing, the first index is inclusive, while the second is exclusive, so mainlist wouldn't contain index 3 but mylist would.
You can do slicing and del.
Slicing to obtain first n elements.
del to delete first n elements.
mainlist = [5,4,3,2,1]
lst = mainlist[:3]
del mainlist[:3]
I'll go ahead and post a couple answers. The easiest way to get some of a list is using slice notation:
pl = pl[:5] # get the first five elements.
If you really want to pop from the list this works:
while len(pl) > 5:
pl.pop()
If you're after a random selection of the choices from that list, this is probably most effective:
import random
random.sample(range(10), 3)
Since this is a list, you can just get the last five elements by slicing it:
last_photos = photos[5:]
This will return a shallow copy, so any edit in any of the lists will be reflected in the other. If you don't want this behaviour you should first make a deep copy.
import copy
last_photos = copy.deepcopy(photos)[5:]
edit:
should of course have been [5:] instead of [:-5] But if you actually want to 'pop' it 5 times, this means you want the list without its last 5 elements...
python - Pop multiple items from the beginning and end of a list - Stack Overflow
python - pop the first N elements - Stack Overflow
Why pop method removes two list at once?
python - The most efficient way to remove the first N elements from a list - Stack Overflow
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:]
I'm doing the Python Crash Course and I got to this exercise, and I was wondering why the pop method is removing two list of my guest.
guest = ['aaron', 'john', 'pedro', 'kevin', 'mark', 'brad']
print(guest)
guest.pop()
print(f"{guest.pop()}")
print(guest)
Output:
['aaron', 'john', 'pedro', 'kevin', 'mark', 'brad']
mark
['aaron', 'john', 'pedro', 'kevin']I tried assigning it with variable now it works. How is it different from the first though?
guest = ['aaron', 'john', 'pedro', 'kevin', 'mark', 'brad']
print(guest)
guest_1 = guest.pop()
print(f"{guest_1}")
print(guest)
Output:
['aaron', 'john', 'pedro', 'kevin', 'mark', 'brad']
brad
['aaron', 'john', 'pedro', 'kevin', 'mark']
You can use list slicing to achieve your goal.
Remove the first 5 elements:
n = 5
mylist = [1,2,3,4,5,6,7,8,9]
newlist = mylist[n:]
print(newlist)
Outputs:
[6, 7, 8, 9]
Or del if you only want to use one list:
n = 5
mylist = [1,2,3,4,5,6,7,8,9]
del mylist[:n]
print(mylist)
Outputs:
[6, 7, 8, 9]
Python lists were not made to operate on the beginning of the list and are very ineffective at this operation.
While you can write
mylist = [1, 2 ,3 ,4]
mylist.pop(0)
It's very inefficient.
If you only want to delete items from your list, you can do this with del:
del mylist[:n]
Which is also really fast:
In [34]: %%timeit
help=range(10000)
while help:
del help[:1000]
....:
10000 loops, best of 3: 161 µs per loop
If you need to obtain elements from the beginning of the list, you should use collections.deque by Raymond Hettinger and its popleft() method.
from collections import deque
deque(['f', 'g', 'h', 'i', 'j'])
>>> d.pop() # return and remove the rightmost item
'j'
>>> d.popleft() # return and remove the leftmost item
'f'
A comparison:
list + pop(0)
In [30]: %%timeit
....: help=range(10000)
....: while help:
....: help.pop(0)
....:
100 loops, best of 3: 17.9 ms per loop
deque + popleft()
In [33]: %%timeit
help=deque(range(10000))
while help:
help.popleft()
....:
1000 loops, best of 3: 812 µs per loop
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']