This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 5 years ago.
Trying to remove negative numbers from a list. I kept running into an issue where two successive negative numbers did not get removed. My code is quite simple:
numbers = [-5, 1, -3, -1]
def remove_neg(num_list):
for item in num_list:
if item < 0:
num_list.remove(item)
print(remove_neg(numbers))
#[1, -1]
I found the answer online after trying 4 different versions of my code and pulling a few hairs out of my head. The answer I found assigned r = numbers[:] and then removed items from r instead of the initial list.
def remove_neg(num_list):
r = numbers [:]
for item in num_list:
if item < 0:
r.remove(item)
print(r)
I understand this concept to have two list variables point to separate data. What I don't understand, is why my initial code doesn't work. Shouldn't for i in numbers: iterate through every item in the list? Why would two successive numbers not be treated the same? I've scoured looking for why and can't seem to find an answer.
In the first example you're modifying the list while iterating over it, which, as you've seen, messes up the iteration. While the second example works, it's very inefficient, and it would be much easier to use a list comprehension to construct a new list without the negatives:
def remove_neg(num_list):
return [x for x in num_list if x > 0]
Related
This question already has answers here:
Is there a simple way to delete a list element by value?
(25 answers)
Closed 3 months ago.
For example:
list = [1,7,2,8,9,2,7,9,2,8,2]
How can I remove two of the "2" without removing the others?
You can find the index of the one(s) you want to delete and use the function pop(index) to delete it/them.
Exemple:
your_list.pop(5) # Delete the 5th element of your list
Here's a little doc: https://www.programiz.com/python-programming/methods/list/pop
This should work by removing an i element n times from a list arr.
arr = [1,7,2,8,9,2,7,9,2,8,2]
def remove(arr, i, n = 1):
for _ in range(n):
arr.remove(i)
remove(arr, 2, 3)
print(arr)
This question already has answers here:
Removing duplicates in lists
(56 answers)
Closed 1 year ago.
def my_list(enter_list):
#print(len(enter_list))--> 7 element
for i in range(0, len(enter_list)): # THE PROBLEM IS HERE
count = enter_list.count(enter_list[i])
if count >=2:
enter_list.pop(i)
return enter_list
print(my_list(["purple","coffee",2,6,2,"purple","steak"]))
At first there are 7 value in my list. But after I remove one of the same value from my list , my list's value is decreasing. İf I change the ranges range(0,len(enter_list)-2) like this. It works. I dont know how to change ranges automatically. ( I can change the ranges manually but it'll not work everytime. )
['coffee', 6, 2, 'purple', 'steak']
This is the output when I change the ranges manually.
Rather than attempt to modify the range you are iterating over, I would suggest you create a copy of the enter_list list and pop() the elements out of that list. That way you will be iterating over the full list of items, but you will return the modified version of the list without having to dynamically alter the range of your loop, which I don't believe is possible.
To quickly show the technique in your code:
def my_list(enter_list):
output_list = enter_list.copy()
for i in range(0, len(enter_list)):
count = enter_list.count(enter_list[i])
if count >=2:
output_list.pop(i)
return output_list
Here you return output_list, which will be your filtered version, but by copying the enter_list, you ensure you are iterating over the full set.
Just to add: using pop(i) here will likely result in you popping something out of range near the end of the loop, so this type of loop iterating over the elements might work best:
for items in enter_list:
output_list.pop(item)
Then you ensure you are not going to pop() on an out of range index.
You could do like this:
def my_list(lst):
i = 0
while True:
cnt = lst.count(lst[i])
if cnt > 1:
lst.pop(i)
i += 1
if len(lst) == i:
break
return lst
print(my_list(["purple","coffee",2,6,2,"purple","steak"]))
OUTPUT
['coffee', 6, 2, 'purple', 'steak']
The problem with your approach is that, in the for loop, the len of the list is only evaluated once - at the beginning. The reason why decreasing by 2 makes it work is because there are 2 elements which have one duplicate, so the loop does not go out of range.
This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 1 year ago.
vec = [-4,-2,0,2,4]
for x in vec:
if x<0:
print(x)
vec.remove(x)
print(vec)
This is a program to remove negative numbers and retain positive numbers in a list
Without the .remove(x), i printed out -4,-2
But with .remove(x),Why when I print(x), it prints out only -4, and only -4 is removed?
Isn't supposedly -2 will also be printed and removed? Isn't supposedly the vec list finally retains 0,2,4 ?
I have tried putting if x <0 or x==-2 , it doesn't work either instead returning me the same problems
I know I can build a new list like vectwo = [x for x in vec if x>0 or x=0]
but I just can't figured out the logical fallacy in the iteration I built to remove negative numbers.
Dont remove from the list while iterating. It's cleaner to use another list.
vec = [-4,-2,0,2,4]
vec_copy = []
for x in vec:
if x >= 0:
vec_copy.append(x)
print(vec_copy)
You can do this in a single line. But note that you aren't actually removing from numbers from the list, instead you pick the positive items and replace the old list with the new one. It does what you want and it's cleaner this way.
vec = [x for x in vec if x >= 0]
This question already has answers here:
What does "list comprehension" and similar mean? How does it work and how can I use it?
(5 answers)
Closed 6 years ago.
I was reading through an article explaining list comprehensions and came across the following example which is supposed to build a list of non-prime numbers:
noprimes = [j for i in range(2, 8) for j in range(i*2, 50, i)]
I tried breaking the list comprehension down by running both for loops separately in a shell, but I'm still unclear as to the functionality of the statement. It seems that the first loop is supposed to be iterating through the list of numbers from 2 to 8 and then storing each number in j which is then passed to the second (nested?) loop which generates numbers from the current value of i times 2 until 50 in increments of i.
What I've described the actual functionality of the list comprehension?
This list comprehension performs the same as the following code:
noprimes = []
for i in range(2,8):
for j in range(i*2, 50, i):
noprimes.append(j)
This question already has answers here:
Understanding slicing
(38 answers)
Closed 8 months ago.
I do not know much about python, but I am surprised the following code works:
import sys
prev = [sys.maxint]*(5)
j = 0
print prev[j]
print prev[j-1]
In general I thought second print statement should give me an error. Why does this work?
I need to convert some python code into C++, and in C++ this will not work.
mylist[-1] returns the last item of mylist, mylist[-2] the second-to-last item etc.
This is by design. Read the tutorial.
The index of an array l can be an integer in the range [-len(l), len(l)-1] (note: inclusive on both ends). You are familiar with the indices in the range [0, len(l)-1]. The indices in the range [-len(l),-1] are as follows: take i in that range, then l[i] == l[len(l) + i]. Essentially, negative numbers count backwards from the end of the array.
Thus, prev[j-1] = prev[-1] = prev[len(prev) + -1] = prev[5 - 1] = prev[4], or the last element in the array.
That's because j - 1 evaluates to -1, which when used as index of python list, means last element.
In python x[-1] returns the last element in a list