I been having this problem in my code, that i solved and think the solution would help other people.
I have a list of objects and need to check if the objects variables are less, more, equal to other variables, the problem is that i don't always have a object in the list, so python would give an Index Error, because the list would be empty, i tried using try to catch the error but it made the code messy and hard to read.
To simplify, all i wanted was to say: if list[0].value < value2: do this, and if List Index does not exist or the condition is not True than go to else statement.
I will give the solution below and anyone else is free to give others solutions too
The way that i found to do this was, when creating the list append values that are NAN, now the list has values to be checked and if the values are NAN the answer will always be False witch leads to going to else.
I actually was using objects, so i just created a new object with all variables set to NAN.
I used numpy.nan
Couldnt you just check that the list length is greather than the index you want to check and then check the condition. Since and shortcircuts, if the list isnt long enough then the index will not get checked. this means you dont have to create dummy data especially for super long lists like in this case where i want to check index one million. This also saves you having to install and utilise other modules such as numpy
mylist = [1, 3]
index = 1_000_000
if len(mylist) > index and mylist[index] < 2:
print("yay")
else:
print("nay")
Related
I'm creating a for loop with an if statement to append a value to a new variable if a specific condition is met. I did the same thing earlier, without the character range of i, and it worked fine. When I try the code below, it doesn't work and shoots out 'KeyError: 0', which doesn't make sense because merge_image1 is a list and not a dictionary.
Hope someone is able to help out!
behav_op1 and merge_image1 are both lists, where each element is a image file pathway (string).
This is the code that is doing the same thing, minus the character range, but for a different variable and works fine:
for i in behav_op1:
if i == 'Stimuli/Operations (Post-study)/main.png':
behav_opIdentity1.append('maintain')
elif i == 'Stimuli/Operations (Post-study)/supp.png':
behav_opIdentity1.append('suppress')
This is the code causing the issue:
for i in merge_image1:
if i[0:36] == 'Stimuli/Faces/resized_positive_faces':
image_valence1.append('positive')
elif i[0:31] == 'Sitmuli/Faces/resized_neg_faces':
image_valence.append('negative')
If I had to guess, KeyError: 0 is raised in line
if i[0:36] == 'Stimuli/Faces/resized_positive_faces':
where you're giving 0 as a key for i. if i were a String, this should probably work. However, it looks like the elements of merge_image1 aren't just Strings, but they are accessed through a key. A key generally needs to be a String itself instead of an int like 0.
The solution is to double check the type of i and access it according to its type. For instance, if i is a dict (a classical example of a container accessed by a key) consisting of a single pair, you'll need to do something like
if list(i.keys())[0][0:36] == 'Stimuli/Faces/resized_positive_faces':
or (better) use startswith suggested in the comments,
if list(i.keys())[0].startswith('Stimuli/Faces/resized_positive_faces'):
BTW if you want to check the type of i, just do
print(merge_image1[0])
If this fails because of indexing issues, then the whole code should be probably be rewritten to work with whatever merge_image1 type is.
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
,in each input would have not use the same element twice.
class solution():
def __init__(self,array_num,target_num):
self.array_num=array_num
self.target_num=target_num
for t in self.array_num:
for b in self.array_num:
e=t+b
w=self.array_num.index(t),self.array_num.index(b)
y=list(w)
if e==self.target_num:
if y==[0,0]:
break
else:
print(y)
p=[3,3]
so=solution(p,6)
output
[] or nothing
expected output
[0,1]
The problem is that you are asking the list to give you the index if a number like this:
self.array_num.index(t)
This will always give you the first occurrence, which is 0 here, although the loop is actually at the second position with index 1.
To avoid that, reverse the logic: create the loop for the index (use len() and range()), then get the number at that position.
As this question sounds like homework or school assignment, I'll not post a full solution. It should be possible to solve the problem now.
More hints to make your teacher happy:
[0, 0] is not the only solution that results in 6. You want to exclude other invalid combinations as well. Pro tip: there's a nice solution that doesn't require any check and will run faster. It's easy to find once you switched the logic.
Currently you do all work in the constructor of the object. Maybe you want a method that does the actual calculation.
Your variable names are not self-explaining. Don't use so many single letter variables.
I have two lists, pPop and sPop. sPop is pPop after being sorted in ascending numerical order (they're populations of towns/cities).
I also have four other lists, pName, pType, pLat, and pLong, but I'm not really doing anything with them at this point in time.
I need to sort this list of cities by ascending population size, and I basically have been told to do it using what I know currently - which isn't that much. I've tried this using tuples and other stuff, but those fall under things I haven't been taught.
I have to compare sPop to pPop and use the information I get from that to reorder the other four lists, so I can spit them out in a .csv file.
I get the idea, I'm just not sure of the execution. I think I need to run a loop over all of sPop, with a loop inside that running for all pPop, which checks if sPop[x] = pPop[y], (x from 0 to len(sPop)) giving some kind of affirmative response when it's true. If it's true, then set pVar[y] equal to sVar[x].
After writing this out it seems fine, I'm just not entirely sure how to loop for every index in python. When I do, say,
for x in sPop
it's
x = sPop[i] i=range(0:len(sPop))
when I'd prefer x to refer to the index itself, not the value of the array/list at that index.
Short version: loop over indices in an array with
for x in array
where x refers to the index. How do? If you can't, best way to refer to the index within a loop? It's late and my brain is fried on this problem after spending about six hours trying to work this out a few days ago using different methods.
EDIT:
Alright, got it. For anyone who is somehow curious (maybe someone'll stumble across this one in five years), you loop over sPop, then over pPop, (use
for indexX, varX in enumerate(list) twice) then use
if varX ==varY
sortedList.append(initialList[varY])
Can't put down the actual code or I'd probably get smacked with a plagiarism checker.
To get the index:
for index, x in enumerate(sPop):
print index, x
for x in range(len(sPop)):
item = sPop[x]
Im trying to write a function but simply cant get it right. This is supposed to be a merge function the merges as follows: the function recieves as an input a list of lists(m lists, all ints). The function creates a list that contains the indexes of the minimun values in each list of the input(each list of the list of lists, overall m indexes). example:
lst_of_lsts= [[3,4,5],[2,0,7]]
min_lst= [0,1]
At each stage, the function chooses the minimum value from that list and adds it to a new list called merged. Then, it erases it from the list of indexes(min_lst) and adds the next index which is now the new minimum.
At the end it returns merged which is an organized list from small ints to big ints. example:
merged= [0,2,3,4,5,7]
Another thing is that Im not allowed to change the original input.
def min_index(lst):
return min(range(len(lst)), key=lambda n: lst[n])
def min_lists(lstlst):
return [min_index(lst) for lst in lstlst]
then
min_lists([[3,4,5],[2,0,7]]) # => [0, 1]
Edit:
This site doesn't exist to solve your homework for you. If you work at it and your solution doesn't do what you expect, show us what you've done and we'll try to point out your mistake.
I figure my solution is OK because it's correct, but in such a way that your teacher will never believe you wrote it; however if you can understand this solution it should help you solve it yourself, and along the way teach you some Python-fu.
I have a list of lists that looks like:
floodfillque = [[1,1,e],[1,2,w], [1,3,e], [2,1,e], [2,2,e], [2,3,w]]
for each in floodfillque:
if each[2] == 'w':
floodfillque.remove(each)
else:
tempfloodfill.append(floodfillque[each[0+1][1]])
That is a simplified, but I think relevant part of the code.
Does the floodfillque[each[0+1]] part do what I think it is doing and taking the value at that location and adding one to it or no? The reason why I ask is I get this error:
TypeError: 'int' object is unsubscriptable
And I think I am misunderstanding what that code is actually doing or doing it wrong.
In addition to the bug in your code that other answers have already spotted, you have at least one more:
for each in floodfillque:
if each[2] == 'w':
floodfillque.remove(each)
don't add or remove items from the very container you're looping on. While such a bug will usually be diagnosed only for certain types of containers (not including lists), it's just as terrible for lists -- it will end up altering your intended semantics by skipping some items or seeing some items twice.
If you can't substantially alter and enhance your logic (generally by building a new, separate container rather than mucking with the one you're looping on), the simplest workaround is usually to loop on a copy of the container you must alter:
for each in list(floodfillque):
Now, your additions and removals won't alter what you're actually looping on (because what you're looping on is a copy, a "snapshot", made once and for all at loop's start) so your semantics will work as intended.
Your specific approach to altering floodfillque also has a performance bug -- it behaves quadratically, while sound logic (building a new container rather than altering the original one) would behave linearly. But, that bug is harder to fix without refactoring your code from the current not-so-nice logic to the new, well-founded one.
Here's what's happening:
On the first iteration of the loop, each is [1, 1, 'e']. Since each[2] != 'w', the else is executed.
In the else, you take each[0+1][1], which is the same as (each[0+1])[1]. each[0+1] is 1, and so you are doing (1)[1]. int objects can't be indexed, which is what's raising the error.
Does the floodfillque[each[0+1] part
do what I think it is doing and taking
the value at that location and adding
one to it or no?
No, it sounds like you want each[0] + 1.
Either way, the error you're getting is because you're trying to take the second item of an integer... each[0+1][1] resolves to each[1][1] which might be something like 3[1], which doesn't make any sense.
The other posters are correct. However, there is another bug in this code, which is that you are modifying floodfillque as you are iterating over it. This will cause problems, because Python internally maintains a counter to handle the loop, and deleting elements does not modify the counter.
The safe way to do this is to iterate of a copy of the loop:
for each in floodfillque[ : ]:
([ : ] is Python's notation for a copy.)
Here is how I understand NoahClark's intentions:
Remove those sublists whose third element is 'w'
For the remaining sublist, add 1 to the second item
If this is the case, the following will do:
# Here is the original list
floodfillque = [[1,1,'e'], [1,2,'w'], [1,3,'e'], [2,1,'e'], [2,2,'e'], [2,3,'w']]
# Remove those sublists which have 'w' as the third element
# For the rest, add one to the second element
floodfillque = [[a,b+1,c] for a,b,c in floodfillque if c != 'w']
This solution works fine, but it is not the most efficient: it creates a new list instead of patching up the original one.