Removed element from list but range has changed? - python

I just learnt how to remove something from a list.
rando = keywords[random.randint(0, 14)]
h = 0
for h in range(len(keywords)):
if rando == keywords[h]:
position = h
realAns = definitions[position]
del keywords [h]
However, as I am using a while loop, a part of the code keeps repeating, and as I have changed the range by deleting an element, a traceback error occurs saying that it is out of range. How do i fix this?
Thanks :)

The code looks fine, may be you have not defined the list 'keywords' with 14 entries in the list.
You get the 'list out of range' error when you are trying to access a part of list which is not defined.
For example see following code
list_of_rollnumbers = [11,24,31,57,42,99,132]
print list_of_rollnumbers[7]
print list_of_rollnumbers[9] #both these would give list index out of range error
print list_of_rollnumbers[5] #this would print 99

Why are you even doing that loop? As I understand it, you pick the item at a random index, then look through the whole list to find the item so you can find its index. Just do:
position = random.randrange(len(keywords))
rando = keywords[position]
realAns = definitions[position]
Or, much simpler:
rando, realAns = random.choice(list(zip(keywords, definitions)))

Related

Nested For Loop Copies the last line in set of indicies

for each in Dti:
i = 0
for each in Dti[0]:
xbi[t][i] = Dti[t][i]
print(t)
i = i + 1
t = t + 1
this is just a test that I'm doing to figure out why my complicated code isn't working. I'm trying to iterate through a list and then each value in the list to set a new list of lists equal to that value. I know I could just set them equal to each other, but it needs to be done this way for my more complicated program. Any tips? I'm getting Dti[-1] for each xbi[t]. I've tried with while too and got the same results
Try something like this:
for t, D in enumerate(Dti)
for i, d in enumerate(D):
xbi[t][i] = d
print(t)
You can use slicing in assignments to replace one list's elements with the elements of another list:
for t, row in enumerate(Dti):
xbi[t][:] = row

How can I append the same element several times in python?

I am creating a GUI with NUMBER of line edits. However, to get the text that is written in them I tried to make a list of LineEdits and append/add a LineEdit element to the list for each iteration.
Then I tried to add the current item to the layout and when pushing continue be able to change the NAME_LIST to the rename lineEdits.
I have tried to written out the length of the self.lineEditRename and it seems as the same item cannot be appended several times. Is this right, and how can I get around this?
I get this error when I run the file..
layout.addWidget(self.lineEditRename[i],2,i)
IndexError: list index out of range
please help:)
# NAME LIST
self.NAME_LIST = []
for i in range(0, NUMBER):
self.NAME_LIST.append("NUMBER: "+ str(i))
for i in range(0,NUMBER+1):
print(i)
if (i==0):
layout.addWidget(QtWidgets.QLabel("Rename: "),2,i))
else:
layout.addWidget(QtWidgets.QLabel(self.NAME_LIST[i-1]),0,i)
self.lineEditRename = [QtWidgets.QLineEdit(self), QtWidgets.QLineEdit(self)]
self.lineEditRename.append(QtWidgets.QLineEdit(self))
layout.addWidget(self.lineEditRename[i-1],2,i)
self.QContinueButton = QtWidgets.QPushButton("Continue")
self.QContinueButton.clicked.connect(lambda: self.windowtwo(NUMBER))
layout.addWidget(self.QContinueButton,10,2)
def windowtwo(self, NUMBER):
for i in range(1,NUMBER+1):
print(self.lineEditRename[i].text())
self.NAME_LIST[i-1]=self.lineEditRename[i].text()
self.switch_window.emit()
Your issue is because of this line self.lineEditRename = [QtWidgets.QLineEdit(self), QtWidgets.QLineEdit(self)]. The length of self.lineEditRename will always be 3 so as soon as i becomes 3, you will get a IndexError: list index out of range.
Did you mean to do this instead:
self.lineEditRename = [QtWidgets.QLineEdit(self), QtWidgets.QLineEdit(self)]
for i in range(0,NUMBER+1):
print(i)
if (i==0):
layout.addWidget(QtWidgets.QLabel("Rename: "),2,i))
else:
layout.addWidget(QtWidgets.QLabel(self.NAME_LIST[i-1]),0,i)
self.lineEditRename.append(QtWidgets.QLineEdit(self))
layout.addWidget(self.lineEditRename[i],2,i)

Finding indexes of a specific repeated number in array

I am trying to get the index of some repeated elements in an array. Here is the code:
cc = []
ang=[12,13,89.0,14,15,16,89.0,17]
class Index:
def __init__(self, **kwargs):
self.Angle = kwargs['Angle']
def ind(self):
for mm in range(0, len(self.Angle)):
if self.Angle[mm] == 89.0:
ee = self.Angle.index(self.Angle[mm])
cc.append(ee)
return cc
plus = Index(Angle=ang)
plus1 = plus.ind()
print (plus1)
I want to find the index of the repeated number = 89.0 in the list (ang). I am expecting to get [2,6] but I keep getting [2,2] which is wrong. Does anybody know how I can fix it? I know it may be possible to do it by changing the format of this code but I prefer to keep this format (using kwargs and class). Thanks!
This is because list.index(<element>) returns the index of the element. If the element appears more than once index() always returns index of the first occurrence.
However, in your code you don't need to call index since you are accessing the element via mm that is already the index. Why not just append mm. Like:
if self.Angle[mm] == 89.0:
cc.append(mm)
Moreover, same code can be elegantly written with list comprehension like:
indexes = [x for x in range(0, len(self.Angle)) if self.Angle[x] == 89.0]

Index error:list assignment index out of range

I want to:
Take two inputs as integers separated by a space (but in string form).
Club them using A + B.
Convert this A + B to integer using int().
Store this integer value in list C.
My code:
C = list()
for a in range(0, 4):
A, B = input().split()
C[a] = int(A + B)
but it shows:
IndexError: list assignment index out of range
I am unable understand this problem. How is a is going out of the range (it must be starting from 0 ending at 3)?
Why it is showing this error?
Why your error is occurring:
You can only reference an index of a list if it already exists. On the last line of every iteration you are referring to an index that is yet to be created, so for example on the first iteration you are trying to change the index 0, which does not exist as the list is empty at that time. The same occurs for every iteration.
The correct way to add an item to a list is this:
C.append(int(A + B))
Or you could solve a hella lot of lines with an ultra-pythonic list comprehension. This is built on the fact you added to the list in a loop, but this simplifies it as you do not need to assign things explicitly:
C = [sum(int(item) for item in input("Enter two space-separated numbers: ").split()) for i in range(4)]
The above would go in place of all of the code that you posted in your question.
The correct way would be to append the element to your list like this:
C.append(int(A+B))
And don't worry about the indices
Here's a far more pythonic way of writing your code:
c = []
for _ in range(4): # defaults to starting at 0
c.append(sum(int(i) for i in input("Enter two space-separated numbers").split()))
Or a nice little one-liner:
c = [sum(int(i) for i in input("Enter two space-separated numbers").split()) for _ in range(4)]

python : list index out of range error while iteratively popping elements

I have written a simple python program
l=[1,2,3,0,0,1]
for i in range(0,len(l)):
if l[i]==0:
l.pop(i)
This gives me error 'list index out of range' on line if l[i]==0:
After debugging I could figure out that i is getting incremented and list is getting reduced.
However, I have loop termination condition i < len(l). Then why I am getting such error?
You are reducing the length of your list l as you iterate over it, so as you approach the end of your indices in the range statement, some of those indices are no longer valid.
It looks like what you want to do is:
l = [x for x in l if x != 0]
which will return a copy of l without any of the elements that were zero (that operation is called a list comprehension, by the way). You could even shorten that last part to just if x, since non-zero numbers evaluate to True.
There is no such thing as a loop termination condition of i < len(l), in the way you've written the code, because len(l) is precalculated before the loop, not re-evaluated on each iteration. You could write it in such a way, however:
i = 0
while i < len(l):
if l[i] == 0:
l.pop(i)
else:
i += 1
The expression len(l) is evaluated only one time, at the moment the range() builtin is evaluated. The range object constructed at that time does not change; it can't possibly know anything about the object l.
P.S. l is a lousy name for a value! It looks like the numeral 1, or the capital letter I.
You're changing the size of the list while iterating over it, which is probably not what you want and is the cause of your error.
Edit: As others have answered and commented, list comprehensions are better as a first choice and especially so in response to this question. I offered this as an alternative for that reason, and while not the best answer, it still solves the problem.
So on that note, you could also use filter, which allows you to call a function to evaluate the items in the list you don't want.
Example:
>>> l = [1,2,3,0,0,1]
>>> filter(lambda x: x > 0, l)
[1, 2, 3]
Live and learn. Simple is better, except when you need things to be complex.
What Mark Rushakoff said is true, but if you iterate in the opposite direction, it is possible to remove elements from the list in the for-loop as well. E.g.,
x = [1,2,3,0,0,1]
for i in range(len(x)-1, -1, -1):
if x[i] == 0:
x.pop(i)
It's like a tall building that falls from top to bottom: even if it is in the middle of collapse, you still can "enter" into it and visit yet-to-be-collapsed floors.
I think the best way to solve this problem is:
l = [1, 2, 3, 0, 0, 1]
while 0 in l:
l.remove(0)
Instead of iterating over list I remove 0 until there aren't any 0 in list
List comprehension will lead you to a solution.
But the right way to copy a object in python is using python module copy - Shallow and deep copy operations.
l=[1,2,3,0,0,1]
for i in range(0,len(l)):
if l[i]==0:
l.pop(i)
If instead of this,
import copy
l=[1,2,3,0,0,1]
duplicate_l = copy.copy(l)
for i in range(0,len(l)):
if l[i]==0:
m.remove(i)
l = m
Then, your own code would have worked.
But for optimization, list comprehension is a good solution.
The problem was that you attempted to modify the list you were referencing within the loop that used the list len(). When you remove the item from the list, then the new len() is calculated on the next loop.
For example, after the first run, when you removed (i) using l.pop(i), that happened successfully but on the next loop the length of the list has changed so all index numbers have been shifted. To a certain point the loop attempts to run over a shorted list throwing the error.
Doing this outside the loop works, however it would be better to build and new list by first declaring and empty list before the loop, and later within the loop append everything you want to keep to the new list.
For those of you who may have come to the same problem.
I am using python 3.3.5. The above solution of using while loop did not work for me. Even if i put print (i) after len(l) it gave me an error. I ran the same code in command line (shell)[ window that pops up when we run a function] it runs without error. What i did was calculated len(l) outside the function in main program and passed the length as a parameter. It worked. Python is weird sometimes.
I think most solutions talk here about List Comprehension, but if you'd like to perform in place deletion and keep the space complexity to O(1); The solution is:
i = 0
for j in range(len(arr)):
if (arr[j] != 0):
arr[i] = arr[j]
i +=1
arr = arr[:i]
x=[]
x = [int(i) for i in input().split()]
i = 0
while i < len(x):
print(x[i])
if(x[i]%5)==0:
del x[i]
else:
i += 1
print(*x)
Code:
while True:
n += 1
try:
DATA[n]['message']['text']
except:
key = DATA[n-1]['message']['text']
break
Console :
Traceback (most recent call last):
File "botnet.py", line 82, in <module>
key =DATA[n-1]['message']['text']
IndexError: list index out of range
I recently had a similar problem and I found that I need to decrease the list index by one.
So instead of:
if l[i]==0:
You can try:
if l[i-1]==0:
Because the list indices start at 0 and your range will go just one above that.

Categories