I'm new to python/jmespath and am trying to sort the below students by their final grade in 2024. I'm sure I can come up with something in python to do it but was just wondering if there is any jmespath magic I can use. I have seen sort_by and know how to search/sort by simple attributes, but haven't yet found anything that can do this.
{
"school": "lame",
"students": [
{
"id": 1,
"name": "Joe",
"grades": [
{"year": 2024, "final": 85},
{"year": 2023, "final": 73}
]
},
{
"id": 2,
"name": "Pedro",
"grades": [
{"year": 2024, "final": 92},
{"year": 2023, "final": 90}
]
},
{
"id": 3,
"name": "Mary",
"grades": [
{"year": 2024, "final": 88},
{"year": 2023, "final": 70}
]
}
]
}
Assuming that you want to sort by the latest year (not specifically the value 2024
), you could achieve it with this:
jmespath.search("students | sort_by(@,&grades|max_by(@,&year).final)", data)
That would result in:
[{'id': 1,
'name': 'Joe',
'grades': [{'year': 2024, 'final': 85}, {'year': 2023, 'final': 73}]},
{'id': 3,
'name': 'Mary',
'grades': [{'year': 2024, 'final': 88}, {'year': 2023, 'final': 70}]},
{'id': 2,
'name': 'Pedro',
'grades': [{'year': 2024, 'final': 92}, {'year': 2023, 'final': 90}]}]
If you actually wanted to sort by the year 2024 specifically, you could use this:
jmespath.search("students | sort_by(@,&(grades[?year==`2024`].final)[0])", data)
But you would gen an error if you have any student record without any grade in 2024, as the index selector [0]
would return null.
In that case you have two options:
If you want to ignore students without 2024 grade, you could use this:
jmespath.search("students[?grades[?year==`2024`]] | sort_by(@,&(grades[?year==`2024`].final)[0])", data)
If you want to sort them at the end or beginning:
jmespath.search("students | sort_by(@,&(grades[?year==`2024`].final)[0]||`0`)", data)
jmespath.search("students | sort_by(@,&(grades[?year==`2024`].final)[0]||`999`)", data)