0

I want to sort array entries by a value of a sub array in PHP 5.4, but I'm not sure how.

Say I want to sort the array by $result['champions']['stats']['totalSessionsPlayed'] in numerical value.

I googled for a bit and couldn't find anything that targeted this, I may be searching for the wrong thing though.

Any help would be greatly appreciated, thanks in advance!

Example Array:

 {
 "modifyDate": 1393185310000,
 "champions": [
  {
     "id": 75,
     "stats": {
        "totalDeathsPerSession": 58,
        "totalSessionsPlayed": 15,
        "totalDamageTaken": 493121,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 2396,
        "maxChampionsKilled": 6,
        "totalDoubleKills": 4,
        "totalPhysicalDamageDealt": 1585013,
        "totalChampionKills": 51,
        "totalAssists": 100,
        "mostChampionKillsPerSession": 6,
        "totalDamageDealt": 1930578,
        "totalFirstBlood": 0,
        "totalSessionsLost": 6,
        "totalSessionsWon": 9,
        "totalMagicDamageDealt": 325337,
        "totalGoldEarned": 156883,
        "totalPentaKills": 0,
        "totalTurretsKilled": 18,
        "mostSpellsCast": 0,
        "maxNumDeaths": 7,
        "totalUnrealKills": 0
     },
     "name": "Nasus"
  },
  {
     "id": 5,
     "stats": {
        "totalDeathsPerSession": 6,
        "totalSessionsPlayed": 1,
        "totalDamageTaken": 30087,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 145,
        "maxChampionsKilled": 4,
        "totalDoubleKills": 0,
        "totalPhysicalDamageDealt": 58659,
        "totalChampionKills": 4,
        "totalAssists": 14,
        "mostChampionKillsPerSession": 4,
        "totalDamageDealt": 93944,
        "totalFirstBlood": 0,
        "totalSessionsLost": 0,
        "totalSessionsWon": 1,
        "totalMagicDamageDealt": 35285,
        "totalGoldEarned": 11514,
        "totalPentaKills": 0,
        "totalTurretsKilled": 1,
        "mostSpellsCast": 0,
        "maxNumDeaths": 6,
        "totalUnrealKills": 0
     },
     "name": "XinZhao"
  },
  {
     "id": 76,
     "stats": {
        "totalDeathsPerSession": 8,
        "totalSessionsPlayed": 2,
        "totalDamageTaken": 27123,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 166,
        "maxChampionsKilled": 5,
        "totalDoubleKills": 1,
        "totalPhysicalDamageDealt": 42820,
        "totalChampionKills": 10,
        "totalAssists": 14,
        "mostChampionKillsPerSession": 5,
        "totalDamageDealt": 148776,
        "totalFirstBlood": 0,
        "totalSessionsLost": 0,
        "totalSessionsWon": 2,
        "totalMagicDamageDealt": 105075,
        "totalGoldEarned": 19656,
        "totalPentaKills": 0,
        "totalTurretsKilled": 3,
        "mostSpellsCast": 0,
        "maxNumDeaths": 4,
        "totalUnrealKills": 0
     },
     "name": "Nidalee"
  },
  {
     "id": 74,
     "stats": {
        "totalDeathsPerSession": 8,
        "totalSessionsPlayed": 1,
        "totalDamageTaken": 25708,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 313,
        "maxChampionsKilled": 10,
        "totalDoubleKills": 1,
        "totalPhysicalDamageDealt": 23397,
        "totalChampionKills": 10,
        "totalAssists": 10,
        "mostChampionKillsPerSession": 10,
        "totalDamageDealt": 267380,
        "totalFirstBlood": 0,
        "totalSessionsLost": 0,
        "totalSessionsWon": 1,
        "totalMagicDamageDealt": 243833,
        "totalGoldEarned": 19122,
        "totalPentaKills": 0,
        "totalTurretsKilled": 1,
        "mostSpellsCast": 0,
        "maxNumDeaths": 8,
        "totalUnrealKills": 0
     },
     "name": "Heimerdinger"
  },
  {
     "id": 36,
     "stats": {
        "totalDeathsPerSession": 22,
        "totalSessionsPlayed": 4,
        "totalDamageTaken": 85510,
        "totalQuadraKills": 1,
        "totalTripleKills": 1,
        "totalMinionKills": 545,
        "maxChampionsKilled": 9,
        "totalDoubleKills": 1,
        "totalPhysicalDamageDealt": 90623,
        "totalChampionKills": 11,
        "totalAssists": 28,
        "mostChampionKillsPerSession": 9,
        "totalDamageDealt": 346793,
        "totalFirstBlood": 0,
        "totalSessionsLost": 2,
        "totalSessionsWon": 2,
        "totalMagicDamageDealt": 254140,
        "totalGoldEarned": 37894,
        "totalPentaKills": 0,
        "totalTurretsKilled": 2,
        "mostSpellsCast": 0,
        "maxNumDeaths": 9,
        "totalUnrealKills": 0
     },
     "name": "DrMundo"
  },
  {
     "id": 115,
     "stats": {
        "totalDeathsPerSession": 24,
        "totalSessionsPlayed": 4,
        "totalDamageTaken": 72093,
        "totalQuadraKills": 0,
        "totalTripleKills": 2,
        "totalMinionKills": 684,
        "maxChampionsKilled": 40,
        "totalDoubleKills": 8,
        "totalPhysicalDamageDealt": 70177,
        "totalChampionKills": 48,
        "totalAssists": 24,
        "mostChampionKillsPerSession": 40,
        "totalDamageDealt": 724195,
        "totalFirstBlood": 0,
        "totalSessionsLost": 3,
        "totalSessionsWon": 1,
        "totalMagicDamageDealt": 650827,
        "totalGoldEarned": 51661,
        "totalPentaKills": 0,
        "totalTurretsKilled": 2,
        "mostSpellsCast": 0,
        "maxNumDeaths": 8,
        "totalUnrealKills": 0
     },
     "name": "Ziggs"
  },
  {
     "id": 10,
     "stats": {
        "totalDeathsPerSession": 7,
        "totalSessionsPlayed": 1,
        "totalDamageTaken": 15911,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 95,
        "maxChampionsKilled": 2,
        "totalDoubleKills": 0,
        "totalPhysicalDamageDealt": 15423,
        "totalChampionKills": 2,
        "totalAssists": 4,
        "mostChampionKillsPerSession": 2,
        "totalDamageDealt": 68032,
        "totalFirstBlood": 0,
        "totalSessionsLost": 1,
        "totalSessionsWon": 0,
        "totalMagicDamageDealt": 51891,
        "totalGoldEarned": 6459,
        "totalPentaKills": 0,
        "totalTurretsKilled": 0,
        "mostSpellsCast": 0,
        "maxNumDeaths": 7,
        "totalUnrealKills": 0
     },
     "name": "Kayle"
  },
  {
     "id": 254,
     "stats": {
        "totalDeathsPerSession": 57,
        "totalSessionsPlayed": 8,
        "totalDamageTaken": 275656,
        "totalQuadraKills": 0,
        "totalTripleKills": 1,
        "totalMinionKills": 569,
        "maxChampionsKilled": 16,
        "totalDoubleKills": 8,
        "totalPhysicalDamageDealt": 1396894,
        "totalChampionKills": 73,
        "totalAssists": 79,
        "mostChampionKillsPerSession": 16,
        "totalDamageDealt": 1608228,
        "totalFirstBlood": 0,
        "totalSessionsLost": 5,
        "totalSessionsWon": 3,
        "totalMagicDamageDealt": 26289,
        "totalGoldEarned": 114735,
        "totalPentaKills": 0,
        "totalTurretsKilled": 6,
        "mostSpellsCast": 0,
        "maxNumDeaths": 11,
        "totalUnrealKills": 0
     },
     "name": "Vi"
  },
  {
     "id": 84,
     "stats": {
        "totalDeathsPerSession": 12,
        "totalSessionsPlayed": 1,
        "totalDamageTaken": 40589,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 133,
        "maxChampionsKilled": 9,
        "totalDoubleKills": 0,
        "totalPhysicalDamageDealt": 77620,
        "totalChampionKills": 9,
        "totalAssists": 6,
        "mostChampionKillsPerSession": 9,
        "totalDamageDealt": 141249,
        "totalFirstBlood": 0,
        "totalSessionsLost": 1,
        "totalSessionsWon": 0,
        "totalMagicDamageDealt": 62145,
        "totalGoldEarned": 12596,
        "totalPentaKills": 0,
        "totalTurretsKilled": 0,
        "mostSpellsCast": 0,
        "maxNumDeaths": 12,
        "totalUnrealKills": 0
     },
     "name": "Akali"
  },
  {
     "id": 81,
     "stats": {
        "totalDeathsPerSession": 48,
        "totalSessionsPlayed": 11,
        "totalDamageTaken": 240602,
        "totalQuadraKills": 1,
        "totalTripleKills": 1,
        "totalMinionKills": 1896,
        "maxChampionsKilled": 14,
        "totalDoubleKills": 14,
        "totalPhysicalDamageDealt": 1570961,
        "totalChampionKills": 89,
        "totalAssists": 75,
        "mostChampionKillsPerSession": 14,
        "totalDamageDealt": 1944153,
        "totalFirstBlood": 0,
        "totalSessionsLost": 6,
        "totalSessionsWon": 5,
        "totalMagicDamageDealt": 351296,
        "totalGoldEarned": 147189,
        "totalPentaKills": 0,
        "totalTurretsKilled": 17,
        "mostSpellsCast": 0,
        "maxNumDeaths": 7,
        "totalUnrealKills": 0
     },
     "name": "Ezreal"
  },
  {
     "id": 17,
     "stats": {
        "totalDeathsPerSession": 4,
        "totalSessionsPlayed": 1,
        "totalDamageTaken": 15549,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 213,
        "maxChampionsKilled": 5,
        "totalDoubleKills": 0,
        "totalPhysicalDamageDealt": 55465,
        "totalChampionKills": 5,
        "totalAssists": 2,
        "mostChampionKillsPerSession": 5,
        "totalDamageDealt": 186354,
        "totalFirstBlood": 0,
        "totalSessionsLost": 0,
        "totalSessionsWon": 1,
        "totalMagicDamageDealt": 128342,
        "totalGoldEarned": 13553,
        "totalPentaKills": 0,
        "totalTurretsKilled": 3,
        "mostSpellsCast": 0,
        "maxNumDeaths": 4,
        "totalUnrealKills": 0
     },
     "name": "Teemo"
  },
  {
     "id": 79,
     "stats": {
        "totalDeathsPerSession": 12,
        "totalSessionsPlayed": 3,
        "totalDamageTaken": 48189,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 432,
        "maxChampionsKilled": 6,
        "totalDoubleKills": 2,
        "totalPhysicalDamageDealt": 40141,
        "totalChampionKills": 11,
        "totalAssists": 20,
        "mostChampionKillsPerSession": 6,
        "totalDamageDealt": 344112,
        "totalFirstBlood": 0,
        "totalSessionsLost": 1,
        "totalSessionsWon": 2,
        "totalMagicDamageDealt": 301544,
        "totalGoldEarned": 28523,
        "totalPentaKills": 0,
        "totalTurretsKilled": 2,
        "mostSpellsCast": 0,
        "maxNumDeaths": 6,
        "totalUnrealKills": 0
     },
     "name": "Gragas"
  },
  {
     "id": 126,
     "stats": {
        "totalDeathsPerSession": 5,
        "totalSessionsPlayed": 1,
        "totalDamageTaken": 22882,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 161,
        "maxChampionsKilled": 6,
        "totalDoubleKills": 0,
        "totalPhysicalDamageDealt": 124060,
        "totalChampionKills": 6,
        "totalAssists": 7,
        "mostChampionKillsPerSession": 6,
        "totalDamageDealt": 134709,
        "totalFirstBlood": 0,
        "totalSessionsLost": 0,
        "totalSessionsWon": 1,
        "totalMagicDamageDealt": 10648,
        "totalGoldEarned": 12014,
        "totalPentaKills": 0,
        "totalTurretsKilled": 0,
        "mostSpellsCast": 0,
        "maxNumDeaths": 5,
        "totalUnrealKills": 0
     },
     "name": "Jayce"
  },
  {
     "id": 56,
     "stats": {
        "totalDeathsPerSession": 13,
        "totalSessionsPlayed": 1,
        "totalDamageTaken": 45039,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 86,
        "maxChampionsKilled": 8,
        "totalDoubleKills": 0,
        "totalPhysicalDamageDealt": 194352,
        "totalChampionKills": 8,
        "totalAssists": 4,
        "mostChampionKillsPerSession": 8,
        "totalDamageDealt": 230377,
        "totalFirstBlood": 0,
        "totalSessionsLost": 1,
        "totalSessionsWon": 0,
        "totalMagicDamageDealt": 11050,
        "totalGoldEarned": 14589,
        "totalPentaKills": 0,
        "totalTurretsKilled": 1,
        "mostSpellsCast": 0,
        "maxNumDeaths": 13,
        "totalUnrealKills": 0
     },
     "name": "Nocturne"
  },
  {
     "id": 35,
     "stats": {
        "totalDeathsPerSession": 12,
        "totalSessionsPlayed": 2,
        "totalDamageTaken": 58956,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 173,
        "maxChampionsKilled": 10,
        "totalDoubleKills": 1,
        "totalPhysicalDamageDealt": 274083,
        "totalChampionKills": 18,
        "totalAssists": 20,
        "mostChampionKillsPerSession": 10,
        "totalDamageDealt": 447168,
        "totalFirstBlood": 0,
        "totalSessionsLost": 1,
        "totalSessionsWon": 1,
        "totalMagicDamageDealt": 125728,
        "totalGoldEarned": 30451,
        "totalPentaKills": 0,
        "totalTurretsKilled": 4,
        "mostSpellsCast": 0,
        "maxNumDeaths": 6,
        "totalUnrealKills": 0
     },
     "name": "Shaco"
  },
  {
     "id": 60,
     "stats": {
        "totalDeathsPerSession": 36,
        "totalSessionsPlayed": 7,
        "totalDamageTaken": 159069,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 290,
        "maxChampionsKilled": 14,
        "totalDoubleKills": 3,
        "totalPhysicalDamageDealt": 339038,
        "totalChampionKills": 48,
        "totalAssists": 40,
        "mostChampionKillsPerSession": 14,
        "totalDamageDealt": 982180,
        "totalFirstBlood": 0,
        "totalSessionsLost": 4,
        "totalSessionsWon": 3,
        "totalMagicDamageDealt": 555025,
        "totalGoldEarned": 74004,
        "totalPentaKills": 0,
        "totalTurretsKilled": 2,
        "mostSpellsCast": 0,
        "maxNumDeaths": 8,
        "totalUnrealKills": 0
     },
     "name": "Elise"
  },
  {
     "id": 1,
     "stats": {
        "totalDeathsPerSession": 12,
        "totalSessionsPlayed": 3,
        "totalDamageTaken": 35249,
        "totalQuadraKills": 0,
        "totalTripleKills": 0,
        "totalMinionKills": 108,
        "maxChampionsKilled": 4,
        "totalDoubleKills": 0,
        "totalPhysicalDamageDealt": 26391,
        "totalChampionKills": 6,
        "totalAssists": 26,
        "mostChampionKillsPerSession": 4,
        "totalDamageDealt": 114034,
        "totalFirstBlood": 0,
        "totalSessionsLost": 1,
        "totalSessionsWon": 2,
        "totalMagicDamageDealt": 87641,
        "totalGoldEarned": 25827,
        "totalPentaKills": 0,
        "totalTurretsKilled": 3,
        "mostSpellsCast": 0,
        "maxNumDeaths": 6,
        "totalUnrealKills": 0
     },
     "name": "Annie"
  },
  {
     "id": 62,
     "stats": {
        "totalDeathsPerSession": 184,
        "totalSessionsPlayed": 35,
        "totalDamageTaken": 942852,
        "totalQuadraKills": 0,
        "totalTripleKills": 5,
        "totalMinionKills": 2390,
        "maxChampionsKilled": 19,
        "totalDoubleKills": 41,
        "totalPhysicalDamageDealt": 6088845,
        "totalChampionKills": 294,
        "totalAssists": 259,
        "mostChampionKillsPerSession": 19,
        "totalDamageDealt": 7057221,
        "totalFirstBlood": 0,
        "totalSessionsLost": 13,
        "totalSessionsWon": 22,
        "totalMagicDamageDealt": 242937,
        "totalGoldEarned": 467825,
        "totalPentaKills": 0,
        "totalTurretsKilled": 27,
        "mostSpellsCast": 0,
        "maxNumDeaths": 12,
        "totalUnrealKills": 0
     },
     "name": "MonkeyKing"
  },
  {
     "id": 0,
     "stats": {
        "totalDamageTaken": 3960844,
        "totalTripleKills": 17,
        "totalMinionKills": 14847,
        "maxChampionsKilled": 40,
        "maxLargestCriticalStrike": 1304,
        "totalChampionKills": 980,
        "totalPhysicalDamageDealt": 17450877,
        "rankedPremadeGamesPlayed": 0,
        "totalSessionsLost": 67,
        "totalNeutralMinionsKilled": 9357,
        "totalSessionsWon": 77,
        "totalMagicDamageDealt": 4544191,
        "maxLargestKillingSpree": 28,
        "totalPentaKills": 0,
        "maxTimeSpentLiving": 1516,
        "totalDeathsPerSession": 799,
        "totalQuadraKills": 4,
        "totalSessionsPlayed": 144,
        "totalDoubleKills": 110,
        "totalAssists": 1137,
        "maxTimePlayed": 3951,
        "mostChampionKillsPerSession": 40,
        "totalDamageDealt": 23554634,
        "botGamesPlayed": 0,
        "killingSpree": 454,
        "totalFirstBlood": 0,
        "rankedSoloGamesPlayed": 0,
        "totalHeal": 786891,
        "totalGoldEarned": 1783556,
        "mostSpellsCast": 0,
        "totalTurretsKilled": 126,
        "maxNumDeaths": 14,
        "totalUnrealKills": 0,
        "normalGamesPlayed": 0
     },
     "name": "Combined"
  }
],
"summonerId": value
}
Andrew
  • 4,443
  • 5
  • 33
  • 75

4 Answers4

2

You notation would indicate you have an object rather than an array, but assuming this is just a misrepresentation and you do indeed have an array, usort() should do the trick:

$array = ...; // your starting array
usort($array, function($a, $b) {
    if ($a['stats']['stats3'] == $b['stats']['stats3']) {
        return 0;
    } else if ($a['stats']['stats3'] > $b['stats']['stats3']) {
        return 1;
    } else {
        return -1;
    }
});

Update based on your updated JSON. Assuming that you are not forcing an associative array on decoding the JSON (which your really shouldn't if you don't have a need to): The code might look like this:

$object = json_decode($your_input_json);
usort($object->champions, function($a, $b) {
    return $a->stats->totalSessionsPlayed - $b->stats->totalSessionsPlayed;
});

This will sort your $object->champions array in place.

Mike Brant
  • 70,514
  • 10
  • 99
  • 103
  • 1
    @kingkero I know, but I don't want to throw ternary operators or "string math" into the mix for someone who is obviously learning the language. This will hopefully demonstrate the functionality more clearly. Plus you don;t get bonus points for eliminating a line or two of code at the expense of clarity. – Mike Brant Feb 24 '14 at 18:55
  • I've updated my json response I'm dealing with above. I can ofcourse json_decode it as well, it's just not as easy to read on SO – Andrew Feb 24 '14 at 18:57
  • @User123456789 I updated my answer to give more specific example based on your actual JSON data. – Mike Brant Feb 24 '14 at 19:03
  • You don't need to use ternary operators to shorten this. The compare function needs to return a value less than, equal to or bigger than 0, It doesn't have to be -1 or 1 exactly. So you can just return `a - b`, like I demonstrated in my answer.. – GolezTrol Feb 24 '14 at 19:05
  • @GolezTrol Agreed. Before question was updated, her was showing the values for comparison as strings. With them being integer values a comparision of `$a->stats->totalSessionsPlayed - $b->stats->totalSessionsPlayed` makes more logical sense. I have updated the more specific solution in my answer. – Mike Brant Feb 24 '14 at 19:08
  • That gives me `Warning: Attempt to modify property of non-object` and `Warning: usort() expects parameter 1 to be array, null given` as errors. – Andrew Feb 24 '14 at 19:13
  • @User123456789 The `champions` property should contain an array per the JSON you have shown. Perhaps you should do `var_dump($object)` to see what you actually have. – Mike Brant Feb 24 '14 at 19:15
  • @User123456789 Oh you must be forcing an associative array then. – Mike Brant Feb 24 '14 at 19:15
  • @MikeBrant yeah, would it be better if I use objects instead of an associative array? Or is there a difference when handling the data besides reference markup? – Andrew Feb 24 '14 at 19:23
  • @User123456789 There is a philosophical difference I suppose. If one works in an object-oriented way (which one should be if working with PHP), then you would tend to want to treat things that are object-like (i.e. a set of possibly unrelated properties for a common item) as objects, and treat associative arrays more as one would a hash table. That is a data structure that is simply a key value store to allow key-based lookup for similar items referenced via some key value. To me, when I look at your data structure, I see a "stats" object. – Mike Brant Feb 24 '14 at 19:28
  • @MikeBrant Thank you for the explanation. As you can see, I'm clearly new at all of this. But do not mind learning the correct way to do things. :) – Andrew Feb 24 '14 at 20:04
  • @User123456789 Glad to help. Unfortunately, PHP is a language in which associative arrays (hash tables) seem to be very much overused. This goes back to PHP's pre-object-oriented past I suppose. Use of associative arrays in cases just like yours seems to be a bit of the norm in the vast majority of PHP documentation and code examples still to this day. – Mike Brant Feb 24 '14 at 21:36
0

You should use uasort() with your custom sorting function (callback).

Please read this http://pl1.php.net/manual/en/array.sorting.php for details about various arrays sorting functions.

Robert Trzebiński
  • 1,327
  • 8
  • 16
  • I've updated my array above, I've tried uasort() and didn't have any luck. – Andrew Feb 24 '14 at 18:56
  • I don't believe `uasort()` is what is needed here, as there are no meaningful keys in teh array being sorted such that one would want to maintain key to value association. This function does not make sense on numerically index array. – Mike Brant Feb 24 '14 at 19:10
  • 1
    You are right, but before edit provided array was associative. – Robert Trzebiński Feb 24 '14 at 19:14
0

Try using php's usort(...)

This code is untested, but should at least demonstrate usort(...) (see documentation for more information).

function cmp($a, $b) {
    $a = $a['stats']['totalSessionsPlayed'];
    $b = $b['stats']['totalSessionsPlayed'];
    if ($a == $b) return 0;
    return ($a < $b) ? -1 : 1;
}

usort($result['champions'], "cmp");
bign8
  • 16
  • 2
  • I wouldn't think you would want to use `uasort()` here as there would not be a meaningful key in `champions` array to maintain association to. – Mike Brant Feb 24 '14 at 19:07
0

You can use uasort with a custom callback for sorting. The callback compares two items and returns negative, 0 or postive value to indicate whether item1 is smaller than, equal to or larger than item2.

So you can use it like this:

uasort($array, function($a, $b){
    return (int)($a['stats']['totalAssists']) - (int)($b['stats']['totalAssists']);
});

uasort is very similar to usort, but it preserves keys.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210