Sorting JSON by attribute's value using Python
Question: I have the following JSON file

    
    
    {
       "modifyDate": 1463899037000,
       "champions": [
          {
             "id": 40,
             "stats": {
                "totalDeathsPerSession": 60,
                "totalSessionsPlayed": 18,
                "totalDamageTaken": 246343,
                "totalQuadraKills": 0,
                "totalTripleKills": 0,
                "totalMinionKills": 272,
                "maxChampionsKilled": 3,
                "totalDoubleKills": 0,
                "totalPhysicalDamageDealt": 121345,
                "totalChampionKills": 11,
                "totalAssists": 271,
                "mostChampionKillsPerSession": 3,
                "totalDamageDealt": 238803,
                "totalFirstBlood": 0,
                "totalSessionsLost": 7,
                "totalSessionsWon": 11,
                "totalMagicDamageDealt": 113241,
                "totalGoldEarned": 176088,
                "totalPentaKills": 0,
                "totalTurretsKilled": 10,
                "mostSpellsCast": 0,
                "maxNumDeaths": 9,
                "totalUnrealKills": 0
             }
          },
          {
             "id": 111,
             "stats": {
                "totalDeathsPerSession": 20,
                "totalSessionsPlayed": 4,
                "totalDamageTaken": 60371,
                "totalQuadraKills": 0,
                "totalTripleKills": 0,
                "totalMinionKills": 247,
                "maxChampionsKilled": 3,
                "totalDoubleKills": 0,
                "totalPhysicalDamageDealt": 35727,
                "totalChampionKills": 4,
                "totalAssists": 35,
                "mostChampionKillsPerSession": 3,
                "totalDamageDealt": 190815,
                "totalFirstBlood": 0,
                "totalSessionsLost": 2,
                "totalSessionsWon": 2,
                "totalMagicDamageDealt": 145353,
                "totalGoldEarned": 30823,
                "totalPentaKills": 0,
                "totalTurretsKilled": 2,
                "mostSpellsCast": 0,
                "maxNumDeaths": 7,
                "totalUnrealKills": 0
             }
          },
          {
             "id": 43,
             "stats": {
                "totalDeathsPerSession": 103,
                "totalSessionsPlayed": 24,
                "totalDamageTaken": 335867,
                "totalQuadraKills": 0,
                "totalTripleKills": 0,
                "totalMinionKills": 828,
                "maxChampionsKilled": 10,
                "totalDoubleKills": 2,
                "totalPhysicalDamageDealt": 170141,
                "totalChampionKills": 77,
                "totalAssists": 302,
                "mostChampionKillsPerSession": 10,
                "totalDamageDealt": 923985,
                "totalFirstBlood": 0,
                "totalSessionsLost": 7,
                "totalSessionsWon": 17,
                "totalMagicDamageDealt": 732367,
                "totalGoldEarned": 242157,
                "totalPentaKills": 0,
                "totalTurretsKilled": 12,
                "mostSpellsCast": 0,
                "maxNumDeaths": 8,
                "totalUnrealKills": 0
             }
          },
          {
             "id": 117,
             "stats": {
                "totalDeathsPerSession": 150,
                "totalSessionsPlayed": 36,
                "totalDamageTaken": 494142,
                "totalQuadraKills": 0,
                "totalTripleKills": 0,
                "totalMinionKills": 2017,
                "maxChampionsKilled": 8,
                "totalDoubleKills": 5,
                "totalPhysicalDamageDealt": 297987,
                "totalChampionKills": 102,
                "totalAssists": 418,
                "mostChampionKillsPerSession": 8,
                "totalDamageDealt": 1905782,
                "totalFirstBlood": 0,
                "totalSessionsLost": 13,
                "totalSessionsWon": 23,
                "totalMagicDamageDealt": 1577943,
                "totalGoldEarned": 353798,
                "totalPentaKills": 0,
                "totalTurretsKilled": 15,
                "mostSpellsCast": 0,
                "maxNumDeaths": 12,
                "totalUnrealKills": 0
             }
          },
          {
             "id": 254,
             "stats": {
                "totalDeathsPerSession": 13,
                "totalSessionsPlayed": 2,
                "totalDamageTaken": 43839,
                "totalQuadraKills": 0,
                "totalTripleKills": 0,
                "totalMinionKills": 77,
                "maxChampionsKilled": 8,
                "totalDoubleKills": 0,
                "totalPhysicalDamageDealt": 227018,
                "totalChampionKills": 12,
                "totalAssists": 8,
                "mostChampionKillsPerSession": 8,
                "totalDamageDealt": 247686,
                "totalFirstBlood": 0,
                "totalSessionsLost": 1,
                "totalSessionsWon": 1,
                "totalMagicDamageDealt": 3920,
                "totalGoldEarned": 21321,
                "totalPentaKills": 0,
                "totalTurretsKilled": 0,
                "mostSpellsCast": 0,
                "maxNumDeaths": 9,
                "totalUnrealKills": 0
             }
          }
       ],
       "summonerId": 21193669
    }
    

and I want to get the `id`s of the 3 `champions` that have the most
`totalSessionsPlayed`. To do this, I'd first sort the `champions` by
`totalSessionsPlayed` and then take the first 3 `id`s. How can I do this, or
is there maybe a better way to do this instead of sorting it first?


Answer: If I understand the problem right, you can use `heapq.nlargest` to [partially
sort](https://en.wikipedia.org/wiki/Partial_sorting) your array:

    
    
    import json
    import heapq
    
    dat = json.loads("(your json here)")
    champions = dat['champions']
    tsp_getter = lambda x: x['stats']['totalSessionsPlayed']
    largest = heapq.nlargest(3, champions, key = tsp_getter)
    ids = [c['id'] for c in largest]
    

But probably simple `sorted` will play nice instead of `nlargest` (you can do
your benchmarks to check it):

    
    
    tsp_getter = lambda x: - x['stats']['totalSessionsPlayed']
    largest = sorted(champions, key = tsp_getter)
    ids = [c['id'] for c in largest[:3]]
    

