Reputation: 87
I have imported json and filtred it by name.
def lootprice(json_object, name):
needobj = [obj for obj in json_object if obj['name'] == name][0]
if needobj['have'] < needobj['max']:
return needobj['price']
It works some time and than shows this kind of error:
needobj = [obj for obj in json_object if obj['name'] == name][0]
IndexError: list index out of range
Upvotes: 1
Views: 4731
Reputation: 1439
I commented to try to bait out the fact that you should have come around to the conclusion that you needed an if check for when the list is empty. You are getting IndexError: list index out of range
on line 2 because you are trying to index into an empty list in the cases where you get the error. Because of this we need to define a variable price
to carry a default value and overwrite it if we have a json object with the correct name. If we don't we will simply return that default value and if we do we will do the correct processing you had in your original code.
def lootprice(json_object, name):
# set this to whatever you want the default return to be when json_object doesn't have correct name
price = None
objects = [obj for obj in json_object if obj['name'] == name]
# checks if it is not an empty array and proceeds to process
if not objects:
needobj = objects[0]
if needobj['have'] < needobj['max']:
price = needobj['price']
return price
Upvotes: 0
Reputation: 475
You are creating a list object, taking the first element, and then throwing the list to garbage. If this is in an active site that can get expensive. Putting your list comprehension in a generator comprehension (comprehension inside parens rather than square brackets) and looping over the generator will allow an early return when the first one is found.
def lootprice(json_object, name):
for needobj in (obj for obj in json_object if obj['name'] == name):
if needobj['have'] < needobj['max']:
return needobj['price']
# Return something that tells the user no results where found or,
return None
Now the return happens when both the "name" and "have max" conditions are satisfied. You could move the have-max condition into the if condition but that might make it less readable. If nothing comes out of filtering the json_object for "name" the loop falls down to the exit where you can return a default object, or as coded here, a None that can be checked by the caller. A default object that can be used by the caller but would indicate nothing was found would be more 'pythonic'.
Upvotes: 0
Reputation: 8338
[obj for obj in json_object if obj['name'] == name] is returning empty, which means nothing in json_object has the name searched for. You should catch that exception and return something accordingly.
def lootprice(json_object, name):
try:
needobj = [obj for obj in json_object if obj['name'] == name][0]
except IndexError:
# Return something that tells the user no results where found
return None
if needobj['have'] < needobj['max']:
return needobj['price']
Full example here:
def lootprice(json_object, name):
try:
needobj = [obj for obj in json_object if obj['name'] == name][0]
except IndexError:
return None
if needobj['have'] < needobj['max']:
return needobj['price']
my_object = [
{'obj_id': 1, 'name': 'test1', 'have': 12, 'max': 50, 'price': 11},
{'obj_id': 2, 'name': 'test2', 'have': 12, 'max': 50, 'price': 22},
{'obj_id': 4, 'name': 'test4', 'have': 12, 'max': 50, 'price': 44},
{'obj_id': 5, 'name': 'test5', 'have': 12, 'max': 50, 'price': 55}
]
lootprice(my_object, 'test1') # Returns 11
lootprice(my_object, 'test2') # Returns 22
lootprice(my_object, 'test3') # Returns None
lootprice(my_object, 'test4') # Returns 44
lootprice(my_object, 'test5') # Returns 55
Upvotes: 1