python : list index out of range error 1 - python

I am trying to check if the array I'm returning is empty.
The code i'm trying is:
if (r.json()['negative'][0]['topic']) == "":
the error i'm getting is index out of range error.
I know that means there is nothing in the array, but my code is crashing because it's returning nothing.
Any Ideas?

You are trying to access first element from an empty array r.json()['negative'] which is causing your code to fail.
Check if "negative" key is not empty array after that you can check your condition.
if (r.json()['negative']:
if (r.json()['negative'][0]['topic']) == "":

Don’t put it all in a single line or you lose the ability to know what exactly is going on.
data = r.json()
if 'negative' not in data:
print('negative key is missing')
elif len(data['negative']) == 0:
print('no items in the negative list')
elif 'topic' not in data['negative'][0]:
print('topic is missing')
elif data['negative'][0]['topic'] == '':
print('topic is empty')
else:
# now you can access it safely
print(data['negative'][0]['topic'])

since you are going 3 deep into a set of dictionary in a list in a dictionary- you will almost certainly need to check the length of each container (or check that the key is in the dictionary) as suggested by others, or it is considered more pythonic by some to just capture the exception and move on :
try:
if (r.json()['negative'][0]['topic']) == "":
# do stuff
except IndexError:
# do other stuff
This is the It is better to ask forgiveness than to ask permission principle which is commonly used.

Related

How to use if else on a non-existant value

The contents of the ScheduledStartDate list is either None or a string.
How can I change my codes below to detect and skip the ScheduledStartDate[j] that contains None? And only run the statements when it is not None.
j = 0
while j< len1:
if (ScheduledStartDate[j] == None):
else:
ScheduledStartDate[j] = datetime.datetime.strptime(ScheduledStartDate[j], format)
j=j+1
To my understanding this looks like it should work, however you may want to remove the else statement and just change the logic of your if statement.
j = 0
while j< len1:
if ScheduledStartDate[j] is not None:
ScheduledStartDate[j] = datetime.datetime.strptime(ScheduledStartDate[j], format)
j=j+1
If your objective is to actually remove the None values then you can see how it's done here. Otherwise there is no way to know which values are None and which are strings without going through the entire list.
Also on another note, if you'd like your code to have that nice color scheme you see in all other questions, add the python tag to the question. Makes your code easier to read.

Python3: for-loop break and else (if statement)

Background information:
hey,
I want to do the following: I have a dictionary with IDs as keys and lists with various things as value. One of the items of the value is a string. I want to check, if a list contains this string. And I want to do it for all keys in my dictionary.
If the list contains the string, I want to print "String is valid"
If the list does not contain the string, I want to print "String is NOT valid"
So far, so good.
Furthermore, the lists I want to check depend on one console input of the user, which specifies, which list should be checked. The console input is "number".
My idea was to iterate over my dictionary and my list with a nested for-loop and compare, if the string(the item of the value) is equal to any list item. If it is, I want to break out of the loop. If the String is not found in the list, I want to execute the else-statement to print my "String is not valid" message.
Code snippet:
def validationHelper(myDict, myList):
for key in myDict:
for value in myDict[key][0]:
for item in myList:
if value==item:
validationHelper.true="String is valid"
break
else:
validationHelper.true="Warning: String is NOT valid"
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
if anyList=="two":
return helperfunc(finalDict,myList2)
if anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper.true)
Problem:
I am running this, but no matter if the string is in the list or not, I always get my printout for the else-statement. So, I guess I have an error in reasoning in my for-loop? Or maybe, I did not understand for-loops at all?! I have tried out different indentions with the else-statement, but couldnt solve my problem.
I would suggest you to change your function the following way (without changing the logic):
def validationHelper(myDict, myList):
for key in myDict:
for value in myDict[key][0]:
for item in myList:
if value==item:
return "String is valid" # Add here to exit
return "Warning: String is NOT valid" # will be returned inf nothing will be found in your 3 loops
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
if anyList=="two":
return helperfunc(finalDict,myList2)
if anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper)
This will help you to exit your 3 nested loops as it was mentioned in comments.
Because in the negative case on first wrong occurrence you don't need to check anything else.
Use return to break all of your loop. Having an else statement is not necessary if you don't have any if statement to begin with.
def validationHelper(myDict, myList):
for item in myList:
if item in myDict.values():
return ("String is valid")
return ("String is NOT valid")
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
elif anyList=="two":
return helperfunc(finalDict,myList2)
elif anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper.true)
Using elif instead of multiple if is a better practice. Be careful with indentions next time.
Also you might want to check .keys() and .values()
You can replace:
for key in myDict:
for value in myDict[key][0]:
with:
for value in myDict.values():
The other answers give a good explanation of how to break out of multiple loops. But you could also simplify your code by using Python's built-in functions and list comprehensions, like this:
def validationHelper(myDict, myList):
if any(v in myList for val in myDict.values() for v in val[0]):
validationHelper.true="String is valid"
else:
validationHelper.true="Warning: String is NOT valid"
def validation(anyList,helperfunc):
if anyList=="one":
return helperfunc(finalDict,myList1)
if anyList=="two":
return helperfunc(finalDict,myList2)
if anyList=="three":
return helperfunc(finalDict,myList3)
validation(number, validationHelper)
print(validationHelper.true)
This should be as efficient as your code, since any short circuits at the first match. And it may be a little more readable. (Note that multi-level list comprehensions go in the same order as regular for loops.)

how to subtract a value of a key in python dictionary

I'm learning python and I'm trying to use this function I built and its not working. The function is not changing a single value in the dictionary as it is working now, although it should. I'd like to get some help
def delete_product(diction):
product_to_delete = raw_input()
for key,value in diction.items():
if key == product_to_delete:
value = value - 1
if (value == 0):
del diction[key]
print "removed"
raw_input()
print "we couldnt remove the product because it does not exist"
raw_input()
Mistake in this code snippet:
value = value - 1
if (value == 0):
del diction[key]
Instead of modifying value in the dictionary, you are only modifying local value. So, this function will delete the required entry only when value happens to be 1.
You can modify it as follows or any variation of it:
if value == 1:
del diction[key]
break
else:
diction[key] = value - 1
Moreover, please note that you have to break out of the for loop once the entry is deleted from the dictionary. If you modify the dictionary while you are iterating it, the iterator will not work after that. If you want to delete multiple keys in one iteration, first get list of all keys to be deleted within the loop and delete after the loop.

index error while running a loop over list contents

I have a list like this:
my_array= ["*","device",":","xyz"], ["+","asd","=","10","pdf","=","6"],
["+","dsa","=","1","pqa","=","2","dga","=","12"], ["*"]
What I want to do is:
define('device','xyz')
define('asd','10')
define('pdf','6')
define('dsa','1')
define('pqa','2')
define('dga','12')
The way I approached is:
i=0
while i < len(my_array):
if my_array[i][0]=="*":
print("'",my_array[i][1],"'","'",my_array[i][3:],"'")
elif my_array[i][0]=="+":
print("'",my_array[i][1],"'","'",my_array[i][3],"'")
if my_array[i][4]=="\D":
print("'",my_array[i][4],"'","'",my_array[i][6],"'")
elif my_array[i][7]=="\D":
print("'",my_array[i][7],"'","'",my_array[i][9],"'")
i=i+1
But doing this, I get index error. I know where the problem is, but I cannot fix it with my very bad programming brain. Can someone help me on this?
First review problem seems in
if my_array[i][0]=="*":
print("'",my_array[i][1],"'","'",my_array[i][3:],"'")
because last element in your my_array is ['*'] and it has no other elements and u are trying to access my_array['*'][1] and its give index error.
You have to remove that element or add members who fulfill element index requirement.
Hard-coding the indices is a sure sign you're doing something wrong - the items in my_array have variable lengths, so some of your indices inevitably fail. I think what you want is something like:
for command in my_array:
if command[0] in ("*", "+"):
for start in range(1, len(command), 3):
assignment = command[start:start+3]
if assignment[1] in ("=", ":"):
print assignment[0], assignment[2]
It is worth noting, however, that you seem to be attempting to write a file parser. Although this code solves this specific problem, it is likely that your overall approach could be improved.
With the assumption, that every key in your list has a value attached to it(e.g. there are no two asterisk following after each other) you can make some simplifications:
We'll read the first value as a key of a new dict and the second item as the value.
With the newly tidied up dict(d) you can continue to work easily e.g. in a for loop:
array=["*","device",":","xyz"], ["+","asd","=","10","pdf","=","6"],
["+","dsa","=","1","pqa","=","2","dga","=","12"], ["*"]
d = {}
for list in array:
new_key = None
for item in list:
if item in ['*',':','+','=']: continue
if new_key == None:
new_key = item
else:
d[new_key] = item
new_key = None
for key in d:
define(key,d[key])

how to loop over each changeInfo['changeInfo'][1...x]['Url']

I have the following code snippet ,i want to change it in such a way where I want loop over for each changeInfo['changeInfo'][1..x],how can I do that
for changeInfo in MainchangeInfo:
if (changeInfo['CRStatus'] == 'Fix' and (('Not Provided' in changeInfo['changeInfo'][0]['Url'] or 'Wrong change Provided' in changeInfo['changeInfo'][0]['Url']) or 'NEW' in changeInfo['changeInfo'][0]['Status'] or 'ABANDONED' in changeInfo['changeInfo'][0]['Status'] or 'Yes' not in changeInfo['RNotesStatus'] or 'Provided' not in changeInfo['RCAInfo'] or 'False' in str(changeInfo['IsDevComplete']))):
if 'Wrong change Provided' in changeInfo['changeInfo'][0]['Url'] or changeInfo['changeInfo'][0]['Info'] != 'Available' ://want to loop over for changeInfo['changeInfo'][0]
changeMailBody = changeMailBody + "<tr bgcolor=\"Red\">"
what do you mean by [1..x]?
if you want to loop over the 'first x' elements in changeInfo['changeInfo'] (in which case, did you mean [0..x]?) you can use slice notation:
for item in changeInfo['changeInfo'][:x]:
# do stuff
if you really want from 1 to x, i.e. skipping the first element you can do:
for item in changeInfo['changeInfo'][1:x]:
# do stuff
See docs here:
http://docs.python.org/2.3/whatsnew/section-slices.html
EDIT:
After your clarification in the comment it's clear you don't even need slice notation, you just need for item in changeInfo['changeInfo'] ...I think your full example would look like:
for changeInfo in MainchangeInfo:
for item in changeInfo['changeInfo']:
if (changeInfo['CRStatus'] == 'Fix' and (('Not Provided' in item['Url'] or 'Wrong change Provided' in item['Url']) or 'NEW' in item['Status'] or 'ABANDONED' in item['Status'] or 'Yes' not in changeInfo['RNotesStatus'] or 'Provided' not in changeInfo['RCAInfo'] or 'False' in str(changeInfo['IsDevComplete']))):
if 'Wrong change Provided' in item['Url'] or item['Info'] != 'Available' ://want to loop over for changeInfo['changeInfo'][0]
changeMailBody = changeMailBody + "<tr bgcolor=\"Red\">"
You can do this with an explicit loop:
for change in changeInfo['changeInfo']:
info = change['info']
# do stuff with it
Or, if you want to write it out as a comprehension:
infos = [change['info'] for change in changeInfo['changeInfo']]
Or, if you just want an iterator, not a list:
infos = (change['info'] for change in changeInfo['changeInfo'])
In any case, you will get changeInfo['changeInfo'][0]['info'], then changeInfo['changeInfo'][1]['info'], and so on.
I'm assuming here that changeInfo['changeInfo'] is a list, not a dict whose keys happen to be small integers. If that assumption is wrong, just replace changeInfo['changeInfo'] with changeInfo['changeInfo'].values() in whichever solution you choose. (Of course in that case, the order will be arbitrary, but that's exactly what you should expect from a dict.)
So, in your existing code, instead of this:
if ('Wrong change Provided' in changeInfo['changeInfo'][0]['Url'] or
changeInfo['changeInfo'][0]['Info'] != 'Available'):
… I'd use the generator expression, together with the any function, like this:
if any('Wrong change Provided' in change['Url'] or change['Info'] != 'Available'
for change in changeInfo['changeInfo']):
Now instead of checking whether this condition is true for the first value in changeInfo['changeInfo']—that is, changeInfo['changeInfo'][0]—you're testing whether it's true for any of the values in changeInfo['changeInfo']. Which, as I understand it, is exactly what you wanted.

Categories