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]
Related
This question already has answers here:
if/else in a list comprehension
(12 answers)
Closed 3 months ago.
I have a big list of numbers like;
original_list = [20,10,15,56,80,200,47,12, 4,70,...]
I want to raise the numbers by 20 percent where they are less than 50, and keep the rest as they are in the list in the original order.
Is there any single comprehension method to make the second list without using function? perhaps;
revised_list =[x*1.2 for x in original_list if x < 50 else y for y in original_list]
You need to use the if/else conditional operator on the value production alone, not the whole attempt at a listcomp:
revised_list = [x*1.2 if x < 50 else x for x in original_list]
which only applies the multiplier if x < 50, and otherwise preserves the original x value.
To get a varying function you can use the python ternary expression:
revised_list = [x*1.2 if x < 50 else x for x in original_list]
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 do I use itertools.groupby()?
(15 answers)
Closed 3 years ago.
I have a list of values, 7,7,7,7,7,7,7,7,6,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,8,8,8,5,5,5,5,5,5,6,6,6,6,6 etc and I need to split the list into the list of list format every time there is a change in value, such that it becomes [[7,7,7,7,7,7,7,7],[6,6,6,6,6,6],[7,7,7,7,7],[8,8,8,8,8,8,8,8],[5,5,5,5,5,5],[6,6,6,6,6]].
I tried a code as follows, however, it told me that there was an unexpected token "for". Is there any other way that's cleaner (one liners)?
for i, n in enumerate(x):
inds = []
if x[i] != x[i-1]:
inds.append(i)
list(split_after(x, lambda i: i for i in inds))
Edit: I can't use groupby because it requires me to sort the list, and I'm concurrently using this list to sort another list of lines, and I can't reorder the other list because of how it's sorted to be lines running ordered around my entire surface.
You can try the following:
indexes = [index for index, _ in enumerate(x) if x[index] != x[index-1]]
indexes.append(len(x))
final = [x[indexes[i]:indexes[i+1]] for i, _ in enumerate(indexes) if i != len(indexes)-1]
print(final)
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]
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