Python Pop Loop - python

Running into something which seems strange. I use a set of lists to hold some data and if a condition is met in them I want to remove that data from each list.
This is what I have currently. It works and removes everything from the first result but when there's more than one meeting the criteria it leaves them.
agecounter = 0
for matches in List1:
if Condition Met:
List1.pop(agecounter)
List2.pop(agecounter)
List3.pop(agecounter)
agecounter = agecounter + 1
If I have 10 items in those lists and three meet the criteria it'll remove the first one. I can even print the data from the other results meeting the condition. It prints it to the console just fine, doesn't throw an exception but seems to just ignore the pop.
I might be missing something really obvious here but there's no reason for that not to work, is there?

Traverse your list in reverse order
agecounter = len(List1)-1
for matches in reversed(List1):
if Condition Met:
List1.pop(agecounter)
List2.pop(agecounter)
List3.pop(agecounter)
agecounter = agecounter - 1

It's not a good idea to remove elements from a list while iterating over it. You should probably iterate over a copy of your list instead

A full example that shows the problem would help get better answers.
That being said, pop is probably not working as you expect. It's not removing agecounter from the list. It's removing the item at position agecounter.
>>> a = [1,2,3, 4]
>>> a.pop(1)
2
>>> a
[1, 3, 4]
>>> a.pop(2)
4
And when you get higher you're more likely to go off the end, throwing an exception.
>>> a.pop(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: pop index out of range
Adding to #StephenTG's answer you probably want to copy the data rather than modify it during iteration. You can "filter" it using a list comprehension:
a = [1,2,3,4]
>>> b = [2,3]
>>> [x for x in a if x not in b]
[1, 4]

Related

I can't print a specific set in a list in python

coordinates=[(4,5),(5,6,(6,6))]
print(coordinates[3])
result:Traceback (most recent call last):
File "C:\Users\PycharmProjects\pythonProject1\App.py", line 2, in <module>
print(coordinates[3])
IndexError: list index out of range
I want the result to be [6,6] instead of the error message what do you mean i am trying to access a fourth one I am trying to access the 3rd one in the list when i use coordinates[1][2] it gives me a syntax error
You want to double check the way you formatted your list.
From the looks of it, your list has index 0 (4,5) and index 1 (5,6,(6,6)). Your list simply has nothing at index 3 because there are only 2 entries. That's what the error message means.
You might want to change your list into coordinates=[(4,5),5,6,(6,6)], then you have index 0-3.
Try this:
print(coordinates[1][-1])
or
print(coordinates[1][2])
There are 2 problems:
(1) Items in a list are zero-indexed, meaning the first element of L is L[0], second is L[1], etc. So if you want the third item:
print(coordinates[2])
(2) If you just stop there, you'll still get an index out of range exception, because your list has only 2 elements. I think you've misplaced a ):
coordinates=[(4,5),(5,6),(6,6)]
In your question, your list coordinates has 2 elements: (4, 5) and (5, 6, (6, 6)) - notice the nested parentheses. The second item is the set containing 3 elements: 5, 6, and another set (6,6).
Tip: Sometimes I like to put lists on multiple lines, especially if they are nested or contain sets/tuples/other complicated structures. One widely accepted style for this is shown below:
coordinates = [
(4,5),
(5,6),
(6,6),
]
EDIT: Thanks to Ignatius Reilly for catching my missing commas!
Note: you are allowed to have a comma after the last element, which I usually do. It makes it easier to add more elements or rearrange them later using copy/paste.

Explain what would be the output

L=[1,2,3]
print(L[L[2]])
What will be the output?
I am a beginner to python and I am confused by this specific thing in List. I am not understanding what this means.
I 'm going to explain with this list (because you will get IndexError with current list):
L = [1, 2, 3, 4, 5]
print(L[L[2]])
First, Python sees the print() function, in order to call this function, Python has to know it's arguments. So it goes further to evaluate the argument L[L[2]].
L is a list, we can pass an index to the bracket to get the item at that index. So we need to know the index. We go further and calculate the expression inside the first []. It's L[2].
Now we can easily evaluate the expression L[2]. The result is 3.
Take that result and put it instead of L[2]. our full expression is print(L[3]) at the moment.
I think you get the idea now...
From inside to the outside:
step1 -- > print(L[L[2]])
step2 -- > print(L[3])
step3 -- > print(4)
Here what you are doing is, you are getting the value at 2 which should be 3, because python starts from 0 and goes up. So after that the interior braces should be done, and then you find the index at 3 which is too big. Because the indexes only go up to 2, and if I say I had three numbers, and you ask me what the fourth number is, that wouldn't make sense right? So that is the same thing. This would result in an error.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
This means that you are trying to get a value that does not exist. I hope this makes it clear.
L[L[2]] becomes L[3], since L[2] is equal to 3. Then, since there are three elements in L, and indexing starts at 0 in Python, this would result in an IndexError.

to remove the last few components in list with python

a=[3,2,2,3]
a.sort()
a.pop(a[3])
print(a)
a.pop(a[2])
print(a)
I want to delete the last two element in list a after sorting, but I get this error:
[2, 2, 3]
Traceback (most recent call last):
File "E:/Project/8.py", line 5, in <module>
a.pop(a[2])
IndexError: pop index out of range
pop(i) pops the element at index i in the list. When you do a.pop(a[3]), you're popping the element at index a[3]=3. If you want to pop the last element, just do a.pop() without any argument, it will implicitly pop the last element.
The reason you're getting the error is because you're looking up what index to pop by retrieving an integer from the list, so by doing a[2], you are first fetching the value 3 and obviously this is outside of the range of the list.
So as said otherwise, just call pop without the parameter - pop()
Simply make the list equal to itself minus the last two elements.
a=[3,2,2,3]
a.sort()
a=a[:-2]
First of all pop is able to just remove the last element, you don't need to specify the argument.
Removing the sorting as it doesn't change much here you get:
a=[2,2,3,3]
a.pop()
print(a)
a.pop()
print(a)
It should do what you probably wanted.
More context and explanation
As explained in the docs if you optionally specify the parameter to pop - it takes in the index of the element to be removed.
So in yet even more simpler code:
a=[3,2,2,3]
a.pop(a[3])
What it means is:
a[3] - take third element of the list, it's 3 (remember this is 0-indexed)
so in this situation a.pop(a[3]) happens to be the same as a.pop(3)
so it removes the third element
Now your error happens because you do a.pop(a[2]) which is again a 3, and the list is too short.
Others have already pointed out your usage error.
Even easier, just take the slice of list that you want:
a = sorted(a)[:-2]
This sorts the list, strips off the last two entries, and assigns the result back to a.
>>> a = [5, 8, 3, 2]
>>> a = sorted(a)[:-2]
>>> a
[2, 3]
just use the pop function twice without parametrs like this:
a.pop()
a.pop()
If you want to remove the last elements you dont need to pass a parameter to pop. Just call a.pop() twice.
The problem rest in that you are not passing the index but the value of the array in the determinate position. When you do pop of a[3] the value is 3 and that index no longer exist because the array size is 3 and the last index is 2.

IndexError: invalid index

I try to read from a dataset and I want all elements except the last one in train. I get the last element as target. I can print it and all good but when the code reaches train = ... then I get this error: IndexError: invalid index
dataset = np.genfromtxt(open(train_file,'r'), delimiter=',',dtype=None)[1:]
target = [x[401] for x in dataset]
train = [x[0:400] for x in dataset]
I also tried: [x[:-1] for x in dataset] but I get the same error.
Data set is big but this is a sample:
xxx,-0.011451,-0.070532,...,-0.011451,-0.070532,O
Your issue appears to be with understanding how list comprehensions work, and when you might want to use one.
A list comprehension goes through every item in an list, applies a function to it, and may or may not filter out other elements. For instance, if I had the following list:
digits = [1, 2, 3, 4, 5, 6, 7]
And I used the following list comprehension:
squares = [i * i for i in digits]
I would get: [1, 4, 9, 16, 25, 36, 49]
I could also do something like this:
even_squares = [i * i for i in digits if i % 2 == 0]
Which would give me: [4, 16, 36]
Now let's talk about your list comprehensions in particular. You wrote [x[401] for x in dataset], which, in English, reads as "a list containing the 401st element of each item in the list called dataset".
Now, in all likelihood, there aren't more than 402 items in each line of your dataset, meaning that, when you try to access the 401st element of each, you get an error.
It sounds like you're just trying to get all the elements in dataset excluding the last one. To do that, you can use python's slice notation. If you write dataset[:-1], you'll get all items in the dataset other than the last one. Similarly, if you wrote dataset[:-2], you'd get all items except for the last two, and so on. The same works if you want to cut off the front of the list: dataset[1:-1] will give you all items in the list excluding the 0th and last items.
Edit:
Now that I see the new comments on your post, it's clear that you are trying to get the first 401 elements of each item in the dataset. Unfortunately, because we don't know anything about your dataset, it's impossible to say what exactly the issue is.
I just tested this with the following toy code. Your syntax is actually correct. Something is wrong with your input file, not with the way you are selecting elements from your list of arrays.
from numpy import *
a = array(range(1,403))
dataset = []
for i in range(5):
dataset.append(a)
target = [x[401] for x in dataset]
train = [x[0:400] for x in dataset]

Python 2.7.5 .count() being ignored?

I'm trying to debug some code for someone, and have run into a rather odd scenario. The purpose of the code is to search for duplicates in a given list and then return a list with no duplicates. (Note, the person writing the code chose to simply delete the duplicates from the list, when I personally would just add each value to a new list. However, I am still intrigued by the oddity). The code is as follows:
def remove_duplicates(duplicates):
duplicates_del = duplicates
for i in duplicates_del:
if duplicates_del.count(i) > 1:
duplicates_del.remove(i)
return duplicates_del
remove_duplicates([3, 3, 3, 3, 3, 3])
When run, the code will return [3, 3, 3] and after some debugging, I've found that the code will work fine until duplicates_del.count(i) is equal to 4. On the next round, it will completely skip everything inside the for statement and go directly to the return statement, resulting in the answer that we get.
I have learned that changing the if statement to while duplicates_del.count(i) > 1: will make the code run flawlessly.
I've looked into the code for the debugger, and learned that there is a breakpoint class that can ignore counts. Is the if statement somehow triggering this breakpoint, or is there another reason why the code doesn't run fully with an if statement instead of a while loop?
The reason this is happening is because you're iterating over a list while you're removing items. This will mostly always result in unexpected results. Take a look at:
L = [1, 2, 3, 4, 5]
for item in L:
if item == 1 or item == 2 or item == 3:
L.remove(item)
print L
The output is:
[2, 4, 5]
Notice that 2 was never removed. If we print item in each loop, we get:
1
3
5
After python removes 1, the order of the list will change, and 2 won't necessarily be the next item in the loop (in fact, 3 is). Notice how 4 is also skipped.
To avoid such behaviour, you must iterate over a copy of the list. Sadly, what you did was not making a copy. Doing duplicates_del = duplicates will make both objects reference the same identity, so changing an element in one will change it in the other.
You should do this:
def remove_duplicates(duplicates):
for i in duplicates[:]: # Creates a copy of the list
if duplicates.count(i) > 1:
duplicates.remove(i)
return duplicates
You are deleting from the list as you loop over it.
Usually, this means that the item following one that is deleted is skipped over.
In this case remove is removing the first matching element each time, so the entire list is being shifted down. The list iterator doesn't see that the list has changed, so increments to the next item.

Categories