Dicts not being popped from list? [duplicate] - python

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 3 months ago.
The context doesn't matter too much, but I came across the problem that while trying to pop dict objects from a list, it wouldn't delete all of them. I'm doing this to filter for certain values in the dict objects, and I was left with things that should have been removed. Just to see what would happen, I tried deleting every item in the list called accepted_auctions (shown below), but it did not work.
for auction in accepted_auctions:
accepted_auctions.pop(accepted_auctions.index(auction))
print(len(accepted_auctions))
When I tested this code, print(len(accepted_auctions)) printed 44 into the console.
What am I doing wrong?

Modifying a list as you iterate over it will invalidate the iterator (because the indices of all the items are changing as you remove items), which in turn causes it to skip items. Don't do that.
The easiest way to create a filtered list is via a list comprehension that creates a new list, e.g.:
accepted_auctions = [a for a in accepted_auctions if something(a)]
Here's a simple example using a list comprehension to filter a list of ints to only the odd numbers:
>>> nums = list(range(10))
>>> nums
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> nums = [n for n in nums if n % 2]
>>> nums
[1, 3, 5, 7, 9]

Related

Removing item in list in Python3 as a for loop - weird behavior [duplicate]

This question already has answers here:
Strange result when removing item from a list while iterating over it
(8 answers)
Closed 2 years ago.
lst = [1,2,3,4,5]
def rem_items(lst):
for i in lst:
print(lst)
time.sleep(1)
lst.remove(i)
rem_items(lst)
returns
[1, 2, 3, 4, 5]
[2, 3, 4, 5]
[2, 4, 5]
I can understand the first two lines, but why does it remove 3 instead of 2?
And why is it stopping after removing 3, not 2,4,5?
Thanks in advance
You are iterating over the list [1,2,3,4,5] and modifying its length.
Writing
for i in lst:
print(lst)
time.sleep(1)
lst.remove(i)
is the same as writing
lst_iter = iter(lst):
for i in lst_iter:
print(lst)
time.sleep(1)
lst.remove(i)
Internally iterator holds a pointer aka index aka position of current item in the list. The loop directive calls i=next(lst_iter) internally, until StopIteration exception is raised.
In your case calling next(lst_iter) for the 1st time returns first element of list [1,2,3,4,5], which is 1. Calling next(lst_iter) for the 2nd time returns second element of list [2,3,4,5], which is 3.
You are modifying the list while iterating over it. This is generally a Bad Thing to do and can lead to unpredictable results.
See here for more info:
Modifying list while iterating

Add element to the end of the list while moving rest one place back [duplicate]

This question already has answers here:
How to force a list to a fixed size?
(7 answers)
Closed 3 years ago.
so I have an empty list:
my_list = []
I will be adding elements in an infinite loop function, one element each iteration. The list needs to be limited to the max of 10 elements.
Im looking for an effective way to add new elements, while moving old elements one index back.
Ex:
my_list = [0,1,2,3,4,5,6,7,8,9]
and after using (probably):
my_list.append('10')
I wish to see a list like this:
my_list = [1,2,3,4,5,6,7,8,9,10]
(first element was removed, rest were taken one place back)
Thanks in advance!
Looks like you want a deque:
from collections import deque
my_list = [0,1,2,3,4,5,6,7,8,9]
d = deque(my_list, maxlen=len(my_list))
d.append(10)
print(d)
# deque([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], maxlen=10)

Removing a list from repeated members using list comprehension instead of the usual for loop [duplicate]

This question already has answers here:
Remove duplicates from list python
(4 answers)
Closed 4 years ago.
I have learned that I can use the so-called list comprehension to make python 'for loops' shorter if I want to create a list. For example, instead of writing:
b = []
a = [2, 3, 5]
for x in a:
b.append(x**2)
I can write my code like this:
b = [x**2 for x in a]
I was wondering how can I convert the below code to the second shorter format:
lst = [1, 2, 3, 3, 4, 5, 5]
u_lst = []
for x in lst:
if x not in u_lst:
u_lst.append(x)
As #PritoshSingh has pointed out in the comment, a list construction that involves references to items already constructed in the same list is not suitable for the use of a list comprehension, which is best for value mapping and/or filtering based on conditions not involving the list being constructed itself.
The problem you're describing can be best solved by using the dict.from_keys method, which ignores items it has already seen as it reads from the given sequence:
u_list = list(dict.from_keys(lst))
Use collections.OrderedDict in place of dict if you're using Python 3.6 or earlier versions, where order of dict keys is not guaranteed.
From the specific example given it seems like you want u_lst to be a list of unique values only. If so, there is no need for any list comprehensions, just use a set on the original list:
lst = [1, 2, 3, 3, 4, 5, 5]
u_lst = list(set(lst))
Outputs {1, 2, 3, 4, 5} without converting into a list and [1, 2, 3, 4, 5] with it.
Note that using set on a list produces a set, to get it to behave as a list, you would then convert it into a list as above.

Weird behaviour when iterating through list and deleting elements in python [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 4 years ago.
I'm trying to iterate over a Python list and delete each element once I've done some tasks with it, but it jumps one element after each iteration and I don't know why:
>>> simple_list = list(range(10))
>>> simple_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for i in simple_list:
... print(i)
... simple_list.remove(i)
...
0
2
4
6
8
>>> simple_list
[1, 3, 5, 7, 9]
Does anyone know why this is happening? Only the even elements are being removed, and looks like the loop doesn't go through the uneven ones.
Well, your list is shrinking while you are iterating over it. If you want to, just look at the first element while your iterate over it.
while len(simple_list) > 0:
print(simple_list[0])
del simple_list[0]
You can use list comprehension to get copy of the array and then iterate.
simple_list = list(range(10))
for i in simple_list[:]:
print(i)
simple_list.remove(i)
Or this:
for i in simple_list[:]:
simple_list.remove(i)
print(simple_list)
Output:
[]
Ok, found the answer here: Python: Removing list element while iterating over list
You should NEVER delete an element from a list while iterating over it in a for loop. You could use a while loop instead. Or, record the indices of all the elements you want to remove and then delete them after the iteration is complete

append values in a list without sorting python, keeping the appending order [duplicate]

This question already has answers here:
How do I make a flat list out of a list of lists?
(34 answers)
Closed 7 years ago.
I am producing a list of list by this code, it is just a condition for a column of a dataframe named lvl or "Level", then append the index of this condition values, so the problem that i got is that the order of appending is important to me,
for i in range(1,int(24-lvl)):
j=list2[(list2.lvl==(lvl+i))]
jj=[]
jj.append(j.index)
print itertools.chain(jj)
well for example, the answer should be:
[0,100,110,500,501,550,555,89,120,114]
but i get the same list but sorted
[0,89,100,110,114,120,500,501,550,555]
itertools.chain works for me. You need to unpack the list before passing it to chain method.
>>> l = [[1,5],[10,2],[6,9,3]]
>>> list(itertools.chain(*l))
[1, 5, 10, 2, 6, 9, 3]
You can simply do it with list comprehension:
>>> l = [[1,5],[10,2],[6,9,3]]
>>> l_out = [item for sub_l in l for item in sub_l]
>>> l_out
[1, 5, 10, 2, 6, 9, 3]

Categories