I am building a simple function But I am stuck on an error, I am trying to sort json array
based on datetime
defined it the response. But JSON array
also contains some None
and Empty string
dates like ""
. so It is showing
KeyError: 'date' when it sees
None
orempty date value
so I am trying to push these type of value in the last of the sorted json array which have None and empty string values (date).
example_response = [
{
"id": 2959,
"original_language": "Permanent Job",
"date": "2012-10-26",
"absent": False
},
{
"id": 8752,
"original_language": "Intern Job",
"date": "",
"absent": True
},
{
"adult": False,
"id": 1300,
"title": "Training Job",
"date": "2020-07-25",
"absent": False
},
{
"adult": False,
"id": 7807,
"title": "Training Job",
"absent": False
},
]
program.py
def sorting_function(response):
if response == True:
sorted_data = sorted(example_response, key=lambda x: datetime.strptime(x['date'], "%Y-%m-%d"))
print(sorted_data)
return sorted_data
As you can see in example_response
one dict
has empty string and one don't have "date".
When I run this function then it is showing KeyError: 'date'
What I have tried ?
I have also tried using
sorted_data = sorted(example_response, key=lambda x: (x['date'] is None, x['date'] == "", x['date'], datetime.strptime(x['date']), "%Y-%m-%d"))
But it still showing KeyError
.
Any help would be much Appreciated.
CodePudding user response:
Dictionaries have a very useful get() function which you could utilise thus:
example_response = [
{
"id": 2959,
"original_language": "Permanent Job",
"date": "2012-10-26",
"absent": False
},
{
"id": 8752,
"original_language": "Intern Job",
"date": "",
"absent": True
},
{
"adult": False,
"id": 1300,
"title": "Training Job",
"date": "2020-07-25",
"absent": False
},
{
"adult": False,
"id": 7807,
"title": "Training Job",
"absent": False
}
]
example_response.sort(key=lambda d: d.get('date', ''))
print(example_response)
In this case, missing or empty 'date' values would precede any other dates.
Output:
[{'id': 8752, 'original_language': 'Intern Job', 'date': '', 'absent': True}, {'adult': False, 'id': 7807, 'title': 'Training Job', 'absent': False}, {'id': 2959, 'original_language': 'Permanent Job', 'date': '2012-10-26', 'absent': False}, {'adult': False, 'id': 1300, 'title': 'Training Job', 'date': '2020-07-25', 'absent': False}]
CodePudding user response:
Don't call strptime
if x['date']
is None
If the key is
lambda x: (x['date'] is None, datetime.strptime(x['date'], "%Y-%m-%d"))
Then the pair will be computed for all values, which means strptime
will be called on all x['date']
, including those that are None
.
I suggest using a conditional, in order to only call strptime
if x['date']
is not None
:
lambda x: (0, datetime.strptime(x['date'], "%Y-%m-%d")) if x['date'] is not None else (1, 0)
Use x.get('date')
instead of x['date']
if x
might be missing the 'date'
key
If x
is a dict that doesn't have a 'date'
, then attempting to access x['date']
will always cause a KeyError
, even for something as simple as x['date'] is None
.
Instead, you can use dict.get
, which doesn't cause errors. If a value is missing, dict.get
will return None
, or another value which you can provide as a second argument:
x = { "id": 2959, "original_language": "Permanent Job" }
print(x['date'])
# KeyError
print(x.get('date'))
# None
print(x.get('date', 42))
# 42
Finally, the key function for the sort becomes:
lambda x: (0, datetime.strptime(x.get('date'), "%Y-%m-%d")) if x.get('date') is not None else (1, 0)
Note that if the key function becomes too complex, it might be better to write it using def
instead of lambda
:
def key(x):
date = x.get('date')
if date is None:
return (1, 0)
else:
return (0, datetime.strptime(date, "%Y-%m-%d"))