Python when a list of dictionaries includes different keys, how to use if else? (key error)

Question:

I have a list of dictionaries like this. Some data contains both first name and last name, and some data only includes first name:

['info': {'id': 'abc', 'age':23, 'firstname':'tom', 'lastname':'don', 'phone': 1324}]
['info': {'id': 'cde', 'age':24, 'firstname':'sara', 'lastname':'man', 'phone': 1324}]
['info': {'id': 'cdd', 'age':22, 'firstname':'sam', 'phone': 1324}]
['info': {'id': 'fff', 'age':25, 'firstname':'mary', 'phone': 1324}]

There is a library and function that retrieves data based on its id. I need to get the data and make a dataset. ‘Lastname’ is more important data. In case when ‘lastname’ does not exist, I want to get ‘firstname’, so I wrote a code as below and it does not work.

ids = ['abc', 'cde', 'cdd', 'fff']

list = [] 
for id in ids:
    data = library.function(id)
    if data['info']['lastname'] in data['info']:
        new_list1 = [data['info']['id'], data['info']['lastname'], data['info']['phone']]
        list.append(new_list1)
    else:
        new_list2 = [data['info']['id'], data['info']['firstname'], data['info']['phone']]
        list.append(new_list2)
print(list)

I still get keyError:

KeyError: 'lastname'  

How shall I fix the code? Or is there any tips for a case like this?

Asked By: hyeppy

||

Answers:

The most common or easiest way to solve your problem would be Exception Handling. The code that checks for the first name should be inside the try block. What this does is if the computer comes across the exception, instead of firing the exception it executes the Except block. You can get more information with a simple search.

Code:

try:
    if data['info']['lastname'] in data['info']:
        new_list1 = [data['info']['id'], data['info']['lastname'], data['info']['phone']]
        list.append(new_list1)
except KeyError:
    new_list2 = [data['info']['id'], data['info']['firstname'], data['info']['phone']]
        list.append(new_list2)

Of course you can also just replace:

if data['info']['lastname'] in data['info']:

with:

if 'lastname' in data['info'].keys():

This checks if the key ‘lastname’ and then executes the last name search

Answered By: Anshumaan Mishra

Best way is to check if the key exists rather than if a value exists in the key.

Instead of

if data['info']['lastname'] in data['info']:

Try this:

if 'lastname' in data['info']:

Answered By: Jeremy Spradlin

This line:

if data['info']['lastname'] in data['info']:

…doesn’t do what you think it does. It attempts to actually retrieve the value stored at data['info']['lastname'], and then see if that is contained in data['info']. What you want instead is:

if 'lastname' in data['info']:

…which checks if the string 'lastname' is one of the keys in data['info'].

A couple of other notes:

  • It’s bad practice to shadow names of builtins, like list and id.
  • You don’t seem to be accessing any other part of data besides data['info'], so you can simplify your code a bit by assigning just that part to your variable.
  • In this case I’d recommend using the dictionary’s get method, which can retrieve a value if the requested key exists, but otherwise return a default value.

With all that handled, your code could look something like this:

ids = ['abc', 'cde', 'cdd', 'fff']

people = [] 
for person_id in ids:
    data = library.function(person_id)['info']
    # Assigns name to the lastname if it exists in the dict, or else
    # assigns it to firstname
    name = data.get('lastname', data['firstname'])
    people.append([data['id'], name, data['phone']])

print(people)
Answered By: CrazyChucky