Sorting a Multi-Dimensional Array with PHP

Every so often I find myself with a multidimensional array that I want to sort by a value in a sub-array. I have an array that might look like this:

//an array of some songs I like
$songs =  array(
		'1' => array('artist'=>'The Smashing Pumpkins', 'songname'=>'Soma'),
		'2' => array('artist'=>'The Decemberists', 'songname'=>'The Island'),
		'3' => array('artist'=>'Fleetwood Mac', 'songname' =>'Second-hand News')
	);

The problem is thus: I’d like to echo out the songs I like in the format “Songname (Artist),” and I’d like to do it alphabetically by artist. PHP provides many functions for sorting arrays, but none will work here. ksort() will allow me to sort by key, but the keys in the $songs array are irrelevant. asort() allows me to sort and preserves keys, but it will sort $songs by the value of each element, which is also useless, since the value of each is “array()”. usort() is another possible candidate and can do multi-dimensional sorting, but it involves building a callback function and is often pretty long-winded. Even the examples in the PHP docs references specific keys.

So I developed a quick function to sort by the value of a key in a sub-array. Please note this version does a case-insensitive sort. See subval_sort() below.

function subval_sort($a,$subkey) {
	foreach($a as $k=>$v) {
		$b[$k] = strtolower($v[$subkey]);
	}
	asort($b);
	foreach($b as $key=>$val) {
		$c[] = $a[$key];
	}
	return $c;
}

To use it on the above, I would simply type:

$songs = subval_sort($songs,'artist'); 
print_r($songs);

This is what you should expect see:

Array
(
    [0] => Array
        (
            [artist] => Fleetwood Mac
            [song] => Second-hand News
        )
 
    [1] => Array
        (
            [artist] => The Decemberists
            [song] => The Island
        )
 
    [2] => Array
        (
            [artist] => The Smashing Pumpkins
            [song] => Cherub Rock
        )
 
)

The songs, sorted by artist.

Tagged ,

103 thoughts on “Sorting a Multi-Dimensional Array with PHP

  1. Ophidian says:

    That would work as long as no two songs have the same name.

    Your best bet is likely to first divide out into multiple associative arrays (one for artist, one for song, etc…) keyed off of the row number from the main array. After that you can use array_multisort (or whatever the function is named) to get the sorting you want.

  2. Adam S says:

    You’re right, Ophidian, this code only works if no artist is repeated. However, array_mutisort() is for sorting the values in arrays, not for sorting them by a specific value in an array. So you will need two operations – albeit PHP built in functions. In this case, I think the function is a very quick way to specify an array and the key of a key by which to sort. I will rework it to accommodate repeat keys.

  3. fresch says:

    Why not just do:

    function subval_sort($a,$subkey) {
    	foreach($a as $k=>$v) {
    		$b[$k] = strtolower($v[$subkey]);
    	}
    	asort($b);
    	foreach($b as $k=>$v) {
    		$c[] = $a[$k];
    	}
    	return $c;
    }
    

    You basically want to sort by a value in a subarray while keeping key value association. There, it’s all in that sentence. I don’t get why you used the value you wanted to sort by as key and the key as value. This way you won’t have problems with duplicate values.

    I hope you don’t use that coding style and simply did it for brevity. You must be getting hammered with PHP notices about assignment before declaration. ;-P

  4. Adam S says:

    Fresch – I actually took this function, char for char, from a program that has indices that mean something and will never duplicate. I’ve amended the function in the post because, as a general shared function, obviously, it makes more sense this way.

    As for the coding style, what, specifically, do you have a problem with? Dynamic assignment? Not saying $b = array()?

  5. Bill, Shooter Of Bul says:

    I wouldn’t suggest using your sort function for anything memory intensive. you create two more arrays in addition to the first! You really can’t beat usort, for speed and memory without dropping down into a php extension and coding it in c.

  6. Adam S says:

    Hi Bill. It’s a simple function, and should definitely not be used for something that would use more than a few dozen, or maybe a few hundred, records. However, usort() is really not an elegant way to do a simple sort by the value of a specific key in an array; it’s arguable that uasort() could do the above more elegantly by operating on the original array, but it requires a callback function, and in the docs, the callback is specific to the key. So if we add an argument, we’re essentially building a function to do the same as the above function with *slightly* less work.

    The “two arrays” it creates are destroyed on the fly, so, unless the arrays do contain a very large numbers of entries, I think it ought to safely execute quickly in PHP’s memory space, which by default, if I recall, is 8MB per script.

  7. Robbie says:

    This is a great little script that got me started when I couldn’t wrap my head around this problem. (The paradox of programming; staying up for days on end, because you’re so tired that you create bugs that need fixing)
    Thanks! =)

  8. Grumpybum says:

    Thank you for this code! I created a dynamically created leaderboard on my site that takes data from an xml feed for each user in the leaderboard. This allowed me to sort the leaderboard from highest score to lowest score(changed asort to arsort) without having to put the data in to a database and then read it out again.

  9. ramener says:

    Thank you for this wonderful code, i’ve used it in my application and it run smoothly. i’ve modified some part to enable it to sort in reverse.

    — cheers —

  10. theodin says:

    thanks for the tutorial I have been trying to do something like this all morning!

  11. theodin says:

    just a thought you could extend off your function and choose how to sort your array like so:

    function subval_sort($a,$subkey,$sort) {
    	foreach($a as $k=>$v) {
    		$b[$k] = strtolower($v[$subkey]);
    	}
    	$sort($b);
    	foreach($b as $key=>$val) {
    		$c[] = $a[$key];
    	}
    	return $c;
    }
    
    $songs = subval_sort($songs,'artist',arsort); 
    print_r($songs);
    
    
  12. Shoaib Latif says:

    This is indeed good script to sort a multidimensional array. Thnxs for your contribution…

  13. cenneth says:

    thanks for the code, it helped me on the way, really nice!

    just a small contribution, my case was to sort a multidimensional array and sort by filename where the names was partly aphanumerical (ie 5-9.pdf, 5-10.pdf, 5-11.pdf and so on)
    using the function above the sorting was un-native; 10 comes before 2, so the result would be 4-1.pdf, 4-10.pdf, 4-2pdf.. but replace the asort($b); with natsort($b); (using native sort instead) solved the problem so 2 comes before 10.

    thought it might save a few minutes for anyone with similair task.

    best regards

    Cenneth

  14. brij says:

    Thank you for this wonderful code, i've used it in my application and it run smoothly. i've modified some part to enable it to sort in reverse.

  15. Rupert says:

    For those who mention using this to sort in reverse order, just change

    asort($b);

    to

    arsort($b);

  16. Rupert says:

    This helped me alot, BTW. Thanks!

  17. Christoph says:

    thanks a lot. great function!

  18. Christoph says:

    thanks a lot. great function!

  19. Christoph says:

    thanks a lot. great function!

  20. Christoph says:

    thanks a lot. great function!

  21. libeesh says:

    Thanks for the code , it works fine…………..

  22. rodney says:

    I'm new to PHP and found this function… works perfectly. But now I have a multi-dimensional array that I need to sort through. Any ideas how to update function to sort by a value 3 levels down?

  23. Omkar's Lab says:

    Sorting two dimensional array using PHP…

    How to sort multi-dimensional or 2d array in PHP Bookmark It Hide Sites……

  24. willowdan says:

    Hello .. I am very grateful I've found this page, helped me a lot in using the right sorting script.

    Many thanks

  25. Brian says:

    Thanks for this! It took me about 20 seconds to get it working perfectly!

  26. Daniel Burke says:

    Perfect little function! Thanks also to theodin for the added feature. I was wondering if there was such a built-in function of PHP to do this, but its not needed now! Thanks again,

  27. mman says:

    Great function, I just needed to retain the association of the keys of the first array so I added the $key into line 7: $c[$key] = … Now the keys remain the same too.

    function subval_sort($a,$subkey) {
    	foreach($a as $k=>$v) {
    		$b[$k] = $v[$subkey];
    	}
    	asort($b);
    	foreach($b as $key=>$val) {
    		$c[$key] = $a[$key];
    	}
    	return $c;
    } // End of subval_sort
    
  28. tutoriale pc says:

    i see you took this function form php.net http://www.php.net/manual/en/function.asort.php#92122
    it’s a clever function

    • Adam S says:

      Uh… no. I wrote this function, and published it in Jan 09. Someone stole it and posted it to PHP.net, in modified form 6 months later.

      • kristoffe says:

        I modified it slightly and made it more of a visual tutorial. whomever made it first, second, third, then me, we are all helping others and I am thankful for that.

        ๐Ÿ™‚ great work guys.

  29. Ankush says:

    Thanks dude

  30. Mile says:

    wow thanks.
    I actually needed this for a future Mystique widget ๐Ÿ™‚

  31. Ginny says:

    Thanks a million sorting a multi-dimensional array was a total head wreck for me until i discovered this script…. good karma to you!

  32. Scott says:

    Works great! Thanks for posting this.

  33. CJ says:

    Hey Adam, Thanks for posting this code. I will definitely be packaging this up and using it as a core tool for array manipulation. Been scratching my head (on and off) for a few days trying to figure this one out. Not really a programmer so this has really helped me out. Kudos points ๐Ÿ™‚

  34. billy says:

    Thanks very much!
    any thoughts how to arrange by two subkeys?

    as in arrange by artist name, and within artist name have song names arranged as well?

    • Tom says:

      Hey Billy,
      I had to do a sort by two subject keys. The problem with the asort in php is it does not keep order in fields that have the same value. I rewrote a merge sort algorithm I found online to do essentially an asort (keep keys). You can use this to sort one way and then sort again another to essentially get your search by two subkeys. If you want to code shoot me an email at [email protected]

  35. Mat Gilbert says:

    This is one of the first times EVER I have literally typed a question “php sort an array of arrays by values of the sub array” and found a simple, elegant solution the first link I clicked. Thank you!

  36. This is freaking cool!!!

    I ran into a conflict in WordPress between theme and plugin and had to rewrite the query – which eliminated the orderby option.

    Adding a custom field to each page to sort it by was where I was headed and your little gem helped me get there.

    Many, many, many thanks!

  37. mlumaad says:

    This code works in my project. Thanks for this mate. ๐Ÿ™‚

  38. Dyl says:

    Here’s a function which uses a closure to sort multi-dimensional arrays. It accepts more than one key to sort by as well.

    http://www.exorithm.com/algorithm/view/sort_multi_array

  39. Terri Ann says:

    I know you mentioned usort() but callbacks, while a bit more complicated than procedural PHP make the solution to this much easier!

    function compare($a, $b)
    {
        return ($a['artist'] > $b['artist']);
    }
    usort($songs, "compare");

    Much better than unnecessary looping & sorting in my opinion.

  40. Md. Muntasir Enam says:

    Thanks. Though it worked for me but I couldn’t understand how it works.

  41. Charles says:

    Man you are awesome…. I love this and it works fine for me…

  42. puneet says:

    Thanx a lots, awesome function, realy helped me.

  43. puneet says:

    Thanx a lot, awesome function, realy helped me.

  44. Chuck says:

    Is there any way to make list simpler? This is what i use for sorting my multi arrays


    function mdsort($array, $sort, $sorttype)
    {
    $listing=array();
    foreach($array as $key => $value)
    {
    $listing[$key]=$value[$sort];
    }
    $sorttype($listing);
    $keylisting=array();
    foreach($listing as $key => $value)
    {
    $keylisting[]=$key;
    }
    return $keylisting;
    }
    $ylist=mdsort($mainlist, name, asort);

  45. Ankh says:

    That was helpful, thanks.

  46. Jayson says:

    Thank you very much so helpful!

  47. Galactix says:

    Perhaps superfluous, but If your keys are integers, use asort($b, SORT_NUMERIC) in the function. Then you get:


    print_r($modulestats);
    Array (
    [0] => Array ( [module] => 14 [received] => 908 )
    [1] => Array ( [module] => 15 [received] => 897 )
    [2] => Array ( [module] => 6 [received] => 994 )
    )

    $sorted = subval_sort($modulestats, 'module');
    print_r($sorted);
    Array (
    [0] => Array ( [module] => 6 [received] => 994 )
    [1] => Array ( [module] => 14 [received] => 908 )
    [2] => Array ( [module] => 15 [received] => 897 )
    )

  48. Mauro says:

    I don’t know how or why, but I just tried simple vanilla sort() directly on a multidimensional array, and it actually sorted it first by subarray[0] and then by subarray[1] ๐Ÿ˜›

  49. Michiel says:

    Great great function, tnx! Was looking for this a few years back.. If I look at my old code I see a few work-arounds which were a bit more extensive (to say the least).. ๐Ÿ™‚

    Since I was fed up with it, i thought “let’s look again”… and here we are, 6 lines of code… nice!

  50. Charles Garrison says:

    Here is a modified version that is slightly more refined. I added the ability to sort by acceding or descending order from the function call, as well as the ability to keep the index key as suggested by Mman above… Thanks for providing this function Adam!


    function subval_sort( $a, $subkey, $order='asc' ) {
    foreach( $a as $k=>$v )
    $b[$k] = strtolower( $v[$subkey] );
    if( $order === 'dec' )
    arsort( $b );
    else
    asort( $b );
    foreach( $b as $key=>$val )
    $c[$key] = $a[$key];
    return $c;
    }

  51. Great! Marvelous! I was stuck, but now I’m not. Thanx a million!

  52. DanZ says:

    Great script..!! absolutely help my project
    thank you very much ๐Ÿ˜€

  53. Tony Hayes says:

    Thanks that was awesome, worked straight off the bat, I love solutions like that.
    Makes me wonder why PHP doesn’t have an internal function to do this, it seems like it would be such a commonly usable thing.

  54. Sergey says:

    Thanks for this! I can’t believe a function like this isn’t a standard part of php…

  55. Hello, first of all thank you for your wonderful post.

    Secondly, I was wondering if it would be possible to take your function a little further…

    I was looking to sort an array subkey by the order of another array. I have a user generated playlist, then all the songs are gathered. Then I need the gathered songs to be sorted by their trackName and match the order of the song titles the user entered in the Playlist Array.

    I have made a post on Stack Overflow, regarding this possibility but I figured i’d make a post on here as well since you are indeed the original author of this wonderful function.

    If you’re curious the link to the post on Stack Overflow is located here:
    http://stackoverflow.com/questions/6711548/sort-array-subkey-based-on-another-arrays-order

    Otherwise, I would love to hear a response from you… ๐Ÿ™‚

    Thanks!

    -Michael Ecklund

  56. Mad Rog says:

    Very interesting, time saving and useful.

    Thanks!

    I added a few bits of the code together to allow for variables called the same name and sorting via asc or desc.

    function subval_sort( $a, $subkey, $order) {
    foreach( $a as $k=>$v )
    $b[$k] = strtolower( $v[$subkey] );
    if( $order === ‘desc’ )
    arsort( $b );
    else
    asort( $b );
    foreach( $b as $k=>$v )
    $c[] = $a[$k];
    return $c;
    }

    $albums = subval_sort($albums,’name’, ‘asc’);

  57. Marcos says:

    Works very well for me. Now I can sort using different index. Thanks!

  58. Hans says:

    Magic. Worked beautifully – super simple, fast and easy.

    Thanks for sharing.

  59. Great example. I’m glad there’s others out there that are willing to post examples of simple code so others can easily port it to their project. Keep up the good work.

  60. IDW Design says:

    Thanks Adam, you just helped me out of a sticky situation right there!
    Ioan

  61. Hung Nguyen says:

    Thanks Adam,
    You’re so great, your func help me alot.
    Thanks again ^^

  62. Brooks says:

    This just helped me tremendously… And as a fellow phish fan, I thank you.

  63. Mike says:

    Your function seems to have changed the Pumpkins song from “Soma” to “Cherub Rock”. Better start debugging ๐Ÿ˜‰

  64. Jeremy says:

    Wow lots of jerks in the comments here. This saved me the headache of trying to write it myself so thanks! I had an array of objects though so I had to make a slight change to where the values located:

    function subval_sort($a,$subkey) {
    	foreach($a as $k=>$v) {
    		$b[$k] = strtolower($v->$subkey);
    	}
    	asort($b);
    	foreach($b as $key=>$val) {
    		$c[] = $a[$key];
    	}
    	return $c;
    }
    
  65. stefano smania says:

    Thank you! You helped me.

  66. Sam says:

    Thankyou! Worked perfectly!

  67. BoSua says:

    Thank you very much!

  68. Raphie says:

    Awesome, it save me a lot of headaches!

  69. Wes says:

    This is perfect, thank you!

  70. swapna says:

    Thank you,It helped me alot.

  71. Mugwomp says:

    Great little code snippet which I am using to sort a JSON feed from an external site – your code did exactly what I needed – thanks.

  72. Piyush says:

    Hey man,
    Thanks a lot its working fine…

  73. Frankie says:

    Thanks for this! It is very helpful for me!

  74. Just wanted to say thanks for this… have been racking my brain for hours trying to sort a many-multi-dimensional array and this got me pointed in the right direction. Thanks!

  75. kandyjet says:

    damn, code of the day!!! cheers!

  76. […] Credits Questo articolo รจ stato pubblicato in Programmazione, WordPress da alexintosh . Aggiungi il permalink ai segnalibri. /* […]

  77. tarik says:

    thank you man, really thank you ๐Ÿ™‚

  78. Justin says:

    Thank you so much. This is exactly what I needed and it saved me the headache of figuring out my own function.

  79. Xem Phim says:

    Thanks for your solution.
    I have a multi-dimension array have “date” element
    Do you know how to sort by “date”?

    • Adam S says:

      [code]
      function subval_sort($a,$subkey) {
      foreach($a as $k=>$v) {
      $b[$k] = strtolower($v[$subkey]);
      }
      asort($b);
      foreach($b as $key=>$val) {
      $c[] = $a[$key];
      }
      return $c;
      }
      $sorted = subval_sort($array,’date’);
      [/code]

  80. Bart says:

    Works great. Simply explained. Thanks!

  81. Emos says:

    $seriesunique=subval_sort(super_unique($itemarray,’series2′),’series2′);
    function super_unique($array,$key) // Function for Unique Arrays
    {
    $temp_array = array();
    foreach ($array as &$v) {
    if (!isset($temp_array[$v[$key]]))
    $temp_array[$v[$key]] =& $v;

    }

    $array = array_values($temp_array);
    return $array;
    }
    function subval_sort($a,$subkey) { // Function for Alphasorting
    foreach($a as $k=>$v) {
    $b[$k] = strtolower($v[$subkey]);
    }
    asort($b);
    foreach($b as $key=>$val) {
    $c[] = $a[$key];
    }
    return $c;
    }

  82. Jack B says:

    You’ve said that usort isn’t as good but I fail to see how this isn’t better than what you’ve done:

    function cmp($a, $b){
    return strcmp($a[‘artist’], $b[‘artist’]);
    }
    usort($songs, “cmp”);

  83. Rob Haskell says:

    Thanks for sharing! FYI, I came across a sorting problem where certain letters were out of order in the sort column. This was resolved by adding this to the asort() function: asort($b,SORT_LOCALE_STRING); The problem is explained a http://stackoverflow.com/questions/18973064/subval-sort-is-out-of-order. Cheers

  84. naved says:

    Very nice solution … here is also a gud solution of this … http://phpsollutions.blogspot.in/2014/08/sort-multidimentional-array-in-php.html

  85. Anurag says:

    it works for me to solve my problem. Good !

  86. Not bad, but it would be very useful if there was a comparison overview. For example a table comparing the advantages/disadvantages and if it is still maintained.

  87. Brita Jpan says:

    I saw PHP Sort Array By SubArray Value but it didn’t help much. Any ideas how to do this?

  88. Thank you very much for these wonderful tutorials! I am a huge fan of yours since 2011 and still is…

Leave a Reply

Your email address will not be published. Required fields are marked *