3

I'm using JSON data from the SFG WorldCup API.

What I need to do is to find the most recent goal scored by a given team in a given match. To do that, I need to sort by the value of the attribute key in each element of the array that is the attribute of the away_team_events attribute.

Let me illustrate.

Here's sample JSON for France from the ongoing (at the time of writing) France v Switzerland.

"away_team_events": [
            {
                "id": 276, 
                "type_of_event": "goal", 
                "player": "Giroud", 
                "time": "17"
            }, 
            {
                "id": 277, 
                "type_of_event": "goal", 
                "player": "Matuidi", 
                "time": "18"
            }, 
            {
                "id": 278, 
                "type_of_event": "penalty-wrong", 
                "player": "Benzema", 
                "time": "32"
            }, 
            {
                "id": 279, 
                "type_of_event": "goal", 
                "player": "Valbuena", 
                "time": "40"
            }, 
            {
                "id": 281, 
                "type_of_event": "substitution-in", 
                "player": "Pogba", 
                "time": "63"
            }, 
            {
                "id": 282, 
                "type_of_event": "substitution-in", 
                "player": "Koscielny", 
                "time": "66"
            }, 
            {
                "id": 283, 
                "type_of_event": "goal", 
                "player": "Benzema", 
                "time": "67"
            }
        ]

So what I need to do here is find which "id" attribute is greatest, because that will be the latest goal.

How do I sort by a specific attribute like this?

I've seen this question, but I can't really make sense of the answers.

EDIT: rephrase, sorry for the confusion.

I don't need to necessarily rearrange them, but how do I identify which item in the list has the greatest id, and use that?

Community
  • 1
  • 1
evamvid
  • 831
  • 6
  • 18
  • 40
  • 1
    but it appears to be already sorted.. – Fabricator Jun 20 '14 at 20:39
  • @ChristianBerendt: this is a *list of dictionaries*. – Martijn Pieters Jun 20 '14 at 20:43
  • Its already a list and assuming that its populated live, then it will be in the order of the actual events; so the last _event_ will be the last item on the list. – Burhan Khalid Jun 20 '14 at 20:44
  • @MartijnPieters I don't think this question is a duplicate of that one. Despite the title, evamvid isn't looking to sort the list, but to find a maximum value. – Zero Piraeus Jun 20 '14 at 20:46
  • @ZeroPiraeus that's what I'm trying to do. I'll go change the title =) – evamvid Jun 20 '14 at 20:48
  • @ZeroPiraeus: The original version asked to sort. Finding the last element is just using `[-1]`, that'll be a dupe too. – Martijn Pieters Jun 20 '14 at 20:50
  • @Martijn well, no, you'd use `max()` ... and that dupe target doesn't answer the question that OP has. I can't immediately find an alternative dupe for the actual question. – Zero Piraeus Jun 20 '14 at 20:52
  • @ZeroPiraeus: But the data *is already sorted*. So the last element is the maximum too. – Martijn Pieters Jun 20 '14 at 20:58
  • In any case, JSON is *just a serialisation format*. Once you parse it to Python data, all you have is *list of dictionaries*. All the questions about either sorting a list of dictionaries, *or* finding the max of a list of dictionaries apply. The two types of questions are closely related, *they are both solved with the exact same technique*. The technique from the dupe I closed this as is *directly applicable to `max()` as well*. – Martijn Pieters Jun 20 '14 at 21:00
  • 1
    The *other* dupe is [In List of Dicts, find min() value of a common Dict field](http://stackoverflow.com/q/5320871) – Martijn Pieters Jun 20 '14 at 21:29

2 Answers2

5

Here is my solution, which use the max() function. All I have to do is to tell max how to sort, in this case, by the id field:

import json
with open('events.json') as f:
    events = json.load(f)
    event = max(events['away_team_events'], key=lambda ev: ev['id'])
    print event

Output:

{u'type_of_event': u'goal', u'player': u'Benzema', u'id': 283, u'time': u'67'}

Discussion

  • events is a JSON data with just one key: away_team_events
  • events['away_team_events'] is a list of 7 items. From this list, we are going to select an item with the greatest event ID
Hai Vu
  • 37,849
  • 11
  • 66
  • 93
1

If you want "the most X" item in a list, where X is "recent" or anything else, you use max(), which can take an optional key function. operator.itemgetter() is the one you want in this case:

from operator import itemgetter
data = json.loads("whatever")
latest_goal = max(data["away_team_events"], key=itemgetter("id"))

Or (as Martijn and Burhan point out) if you can guarantee that the list of dictionaries is already sorted by id, just getting the last one will work:

latest_goal = data["away_team_events"][-1]
Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
  • would the `latest_goal` variable then contain an index for the list? – evamvid Jun 20 '14 at 21:03
  • @evamvid no, it's just the dictionary that satisfies your criteria. – Zero Piraeus Jun 20 '14 at 21:08
  • I'm having problems today: Traceback says `Traceback (most recent call last): File "C:\Users\User\Docs\Programming\WC.py", line 28, in goalindex = max(math['home_team_events'], key=itemgetter("id")) TypeError: 'Response' object has no attribute '__getitem__'`. So it seems like it's a problem with the JSON I'm getting.... – evamvid Jun 21 '14 at 21:04
  • @evamvid that error has nothing to do with the correctness of this answer; you have a new problem (that you're attempting to treat a HTTP response as though it were the result of parsing a JSON document). You'll need to post a new question. – Zero Piraeus Jun 21 '14 at 21:18
  • I'm not sure if it's really a new problem or not. What I'm trying to figure out is whether the JSON is invalid (as stated above) or if the method you suggested is incompatible because of the way requests returns data...I honestly have no idea what's going on here... – evamvid Jun 23 '14 at 16:25
  • On a side note, when I put in the other answer, it worked, although that basically seems to be doing the same thing as yours. – evamvid Jun 23 '14 at 16:26
  • I did **not** state that "the JSON is invalid"; I told you (just as your traceback told you) that you tried to treat a `Response` object as though it were the result of parsing JSON. That obviously isn't going to work, and has nothing whatsoever to do with the correctness of my answer - which, yes, is identical in substance to Hai Vu's later answer (which also would not have worked if you had tried to do the same thing with it as you tried to do with mine). – Zero Piraeus Jun 23 '14 at 16:47
  • *I* said that. I guess you're right -- the problem is seperate. But, as far as I can tell, I *did* do the same thing with it. That sounds about right about what I did with the response object. I'll double check ASAP (the source from this question is on another computer which I don't have access to right now). – evamvid Jun 24 '14 at 16:06