This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 10 years ago.
I need to delete elements from a list whilst iterating over it (I cannot create a new list as it is referenced in code I have no control over).
The best I've come up with is:
last_index = len(somelist) - 1
for (index,item) in enumerate(reversed(somelist)):
if somecondition(item):
del somelist[last_index - index]
Are there better alternatives? I've seen this post and this one too, but none of the solutions provided are as efficient or as concise (IMHO).
You can use a list comprehension + slice assignment, which is certainly more concise -- I don't know about efficiency (although I would expect it to do better in that regard as well since you don't need to keep shifting elements in the list over every time you delete an item ...)
somelist[:] = [ x for x in somelist if not somecondition(x) ]
Related
This question already has answers here:
Strange result when removing item from a list while iterating over it
(8 answers)
How to remove items from a list while iterating?
(25 answers)
Closed 12 months ago.
I was trying to sort a list using for loops in python.
I wrote the code like this.
L=[1,2,3,6,7,9,4]
NL=[]
for i in L:
NL.append(min(L))
L.remove(min(L))
print(NL)
But here the output is [1, 2, 3, 4].
I can't understand why the output is stopping at 4. I am new to coding. It would be helpful if someone could help me with this.
You're removing elements from a list while looping over it, which is problematic (if the index of the element you're removing is before your current loop index, the "next element" being shifted back by one won't be visited). As you don't need to work with the index anyways, you can simply loop n times, where n is the number of elements in the list (the length of the list):
L=[1,2,3,6,7,9,4]
NL=[]
for _ in range(len(L)):
NL.append(min(L))
L.remove(min(L))
print(NL)
Side note: The algorithm you've implemented is called "selectionsort" and has quadratic time complexity. You're also emptying the input list. In practice, you should usually be using Python's builtin [...].sort() to sort the input list in place; if you want a sorted copy, you can always call [...].copy() first.
This question already has answers here:
Why does Python skip elements when I modify a list while iterating over it?
(8 answers)
Closed 1 year ago.
I have a list that has lists with dictionaries in them. I'm trying to check one of the values for a key inside the dictionary and if it's try then I remove that list from the list. I'm getting a bit confused with the layers of lists and dictionaries going on here and I thought I had a good solution but it seems to mess with the index of the for loop when I do it the way that I thought would work and then only the first match gets removed.
Here's an example of what I have going on.
master_list = [
{"irrelevant_key": "irrevelant_value",
"releveant_key":
[{"first_value": "first_key"}, {"problem_key": 0}],
[{"second_value": "second_key"}, {"problem_key": 1}]
}]
for index, key in enumerate(master_list):
for item in master_list[index]["relevant_key"]:
if item[1]["problem_key"] == 0:
master_list[index]["relevant_key"].remove(item)
So I'm sure there's a more elegant better way to do this with some sort of comprehension but what I'm noticing is that when I delete the item the rest of the items go back one so the iteration doesn't work as I would expect.
It's not a good idea to remove elements from a list while looping through it. You can always make a copy and update it:
import copy
my_list= copy.deepcopy(master_list)
However, a better approach would be to use list comprehensions:
master_list = [{"irrelevant_key": "irrevelant_value",
"relevant_key":
[[{"first_value": "first_key"}, {"problem_key": 0}],
[{"second_value": "second_key"}, {"problem_key": 1}]],
}]
for lst in master_list:
lst['relevant_key'] = [x for x in lst['relevant_key'] if x[1]['problem_key'] != 0 ]
This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 2 years ago.
I want to have a copy of my list, and then sort it, but due of the way that python works, if i sort the copy of the list, it sort also the original list. Here is my code:
def swapBySoting(arr):
newArr = arr
newArr.sort()
swap = 0
for i in range(len(arr)):
if arr[i] != newArr[i]:
swap +=1
return int(swap / 2)
I only need to know how to store the copy in another reference of memory, to sort only the copy. Thanks
Assignment just creates a new alias of an object, it doesn't perform a copy. You have two simple solutions:
Shallow copy the first list when assigning to the second:
newArr = arr[:] # Or arr.copy()
Combine your copy and sort into a single step with the sorted built-in (that creates a new list, sorts it, and returns the new list):
newArr = sorted(arr) # No need to call .sort() afterwards
Side-note: For comparing elements, looping over indices is relatively slow and unpythonic. Using zip and unpacking to useful names gets the much nicer (and a titch faster):
for old, new in zip(arr, newArr):
if old != new:
swap +=1
That said, this algorithm for counting minimum swaps is almost certainly wrong, but that's another question entirely.
This question already has answers here:
Iterating over two lists one after another
(4 answers)
Closed 4 years ago.
I would like to create a list from elements of 2 different lists using list comprehensions.
For instance, assuming my 2 lists are men and women, I want a single list with all names:
men_names = [man.name for man in men]
women_names = [woman.name for woman in women]
all_names = men_names + women_names
Is there a one-line solution to obtain this list? Thanks!
EDIT: Using a list comprehension is a requirement because in my particular case it should be very much faster than building the list in a for loop, and performance is an issue.
Using itertools.chain is a way to achieve this without creating an intermediate list.
from itertools import chain
all_names = [person.name for person in chain(men, women)]
This question already has answers here:
How to remove multiple indexes from a list at the same time? [duplicate]
(8 answers)
Closed 5 years ago.
Although this should be rather easily done with a for loop, I'm wondering wether there is a concise way to delete a set of positions from a Python list. E.g.:
l = ["A","B","C","D","E","F","G"]
pos = [4,6]
# Is there something close to
l.remove(pos)
Best
del is what you are looking for if you have consecutive indices:
From the documentation:
There is a way to remove an item from a list given its index instead of its value: the del statement
Otherwise, you could generate a new list, by filtering out indices, which you aren't interested in
result = [x for i, x in enumerate(l) if i not in pos]