26

I'm trying to sort my PHP hashtable based on a specific value in the inner array. The data structure looks like this:

print_r($mydata);

Array(
[0] => Array
    (
        [type] => suite
        [name] => A-Name
    )
[1] => Array
    (
        [type] => suite
        [name] => C-Name
    )
[2] => Array
    (
        [type] => suite
        [name] => B-Name
    )
)

I've tried ksort, sort, usort but nothing seems to work. I'm trying to sort based on the name key two-levels down.

This was my attempt using usort:

function cmp($a, $b) {
    return $b['name'] - $a['name'];
}

usort($mydata, "cmp");

Is there an easy way to do this or do I need to write a custom sort function?

Skeets
  • 4,476
  • 2
  • 41
  • 67
user1216398
  • 1,890
  • 13
  • 32
  • 40

6 Answers6

77

Thinking,more useful and practical http://php.net/manual/en/function.sort.php

function array_sort($array, $on, $order=SORT_ASC){

    $new_array = array();
    $sortable_array = array();

    if (count($array) > 0) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                foreach ($v as $k2 => $v2) {
                    if ($k2 == $on) {
                        $sortable_array[$k] = $v2;
                    }
                }
            } else {
                $sortable_array[$k] = $v;
            }
        }

        switch ($order) {
            case SORT_ASC:
                asort($sortable_array);
                break;
            case SORT_DESC:
                arsort($sortable_array);
                break;
        }

        foreach ($sortable_array as $k => $v) {
            $new_array[$k] = $array[$k];
        }
    }

    return $new_array;
}

How to use

 $list = array(
   array( 'type' => 'suite', 'name'=>'A-Name'),
   array( 'type' => 'suite', 'name'=>'C-Name'),
   array( 'type' => 'suite', 'name'=>'B-Name')
 );

$list = array_sort($list, 'name', SORT_ASC);

array(3) { [0]=> array(2) { ["type"]=> string(5) "suite" ["name"]=> string(6) "A-Name"    } [2]=> array(2) { ["type"]=> string(5) "suite" ["name"]=> string(6) "B-Name" } [1]=> array(2) { ["type"]=> string(5) "suite" ["name"]=> string(6) "C-Name" } }
voodoo417
  • 11,861
  • 3
  • 36
  • 40
  • 9
    That is a terrifically overcomplicated solution. – deceze Sep 22 '17 at 07:36
  • 1
    @deceze Hi! Thanks for comment and downvote. Could you prove your opinion? Thanks in advance. – voodoo417 Sep 28 '17 at 18:44
  • 20
    `usort($mydata, function ($a, $b) { return strcmp($a['name'], $b['name']); })` — given that this works perfectly fine, yes, I’d say yours is over complicated. – deceze Sep 28 '17 at 19:12
  • @deceze yes, of course. But above ( mine ) is more "common" solution. I could say e.g. 100 situaitions ( actually, infinitely) - where my solution will work without any changes. Single solution. You will write 100 usort-functions ( the same - actually, infinitely). Of course, for unique situation - unique solution. There is just "common" solution. Ok. I have understood you. Maybe, do you write every time for each new project classes like `Response`, `Request`, `Controller` etc. ? – voodoo417 Sep 28 '17 at 21:16
  • 1) For such a short one-liner it’s not all that necessary to write something generic, hardly comparable to MVC infrastructure. 2) Even for a generic function this is pretty complicated; see https://stackoverflow.com/a/22829326/476. – deceze Sep 29 '17 at 05:12
  • @deceze I checking you link..... ))) You made my day. P.S. ok, I have understood U. Thanks for good mood for a whole day ))). – voodoo417 Sep 29 '17 at 07:50
  • @deceze Actually, your solution from link looks really terrible (for me). And your words `....a terrifically overcomplicated solution` now are sounding very funny. Have a nice day!) – voodoo417 Sep 29 '17 at 07:55
  • There's complicated because it's doing something complicated and the code is dense (my example), and then there's complicated because it's doing something needlessly complex for something that could be done in a much simpler way (yours)… – deceze Sep 29 '17 at 09:09
  • @deceze Ok, np. Sorry, I`m stopping discuss because I have heart your opinion - your comments & downvote. And understood your seeing this problem (sorting multi-array). Ok. Have a nice day! – voodoo417 Sep 29 '17 at 09:24
  • I combined both your solutions and used, Thanks @deceze @voodoo417 ```function array_sort($array, $on, $order = SORT_DESC){usort($array, function ($a, $b) use ($on, $order) {switch ($order) {case SORT_ASC:return strcmp($a[$on], $b[$on]);case SORT_DESC:return strcmp($b[$on], $a[$on]);}});return $array;}``` – Mudit Gulgulia Dec 09 '21 at 07:51
13

Try this usort function:

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

$my_array = array(
0 => array
    (
        'type' => 'suite'
        ,'name' => 'A-Name'
    )
,1 => array
    (
        'type' => 'suite'
        ,'name' => 'C-Name'
    )
,2 => array
    (
        'type' => 'suite'
        ,'name' => 'B-Name'
    )
);


usort($my_array, "cmp");

If you using it in a class, the second parameter changes to an array like this:

usort($my_array, array($this,'cmp'));
Ali Seyfollahi
  • 2,662
  • 2
  • 21
  • 29
2

array_multisort() - Sort multiple or multi-dimensional arrays

Andrey Volk
  • 3,513
  • 2
  • 17
  • 29
1
 <?php
$a=array(
array('a'=>5,'b'=>7),array('c'=>4,'d'=>2),array('e'=>0,'f'=>12)

    );
function cmp_sort($x,$y){           //your function to compare two keys
if($x===$y)
    return 0;
else
    return ($x<$y?1:-1);
}

uasort($a,'cmp_sort');    //call user-defined compare function
print_r($a);              //printing the sorted array


?>

Output=>

Array ( [2] => Array ( [e] => 0 [f] => 12 ) [1] => Array ( [c] => 4 [d] => 2 ) [0] => Array ( [a] => 5 [b] => 7 ) )

Lrrr
  • 4,755
  • 5
  • 41
  • 63
Prateek Joshi
  • 3,929
  • 3
  • 41
  • 51
0
$this->aasort($array,"key");

function aasort (&$array, $key) {
    $sorter=array();
    $ret=array();
    reset($array);

    foreach ($array as $ii => $va) {
        $sorter[]=$va[$key];
    }

    arsort($sorter);

    foreach ($sorter as $ii => $va) {
        $ret[]=$array[$ii];
    }

    return $array=$ret;
}
JJJ
  • 32,902
  • 20
  • 89
  • 102
pawan sen
  • 716
  • 5
  • 14
0

try this recursive mode, that I used in Magento REST API:

$parameters = ['searchCriteria' => ['currentPage' => 1, 'pageSize' => 20]];
$parameters['searchCriteria']['filter_groups'][0]['filters'][0] = ['condition_type' => 'from', 'field' => 'updated_at', 'value' => '2017-01-01T00:00:00'];
$parameters['searchCriteria']['filter_groups'][1]['filters'][0] = ['condition_type' => 'to', 'field' => 'updated_at', 'value' => '2017-12-31T23:59:59']; 

function sortArrayByKeyAsc($_params){
    if(is_array($_params)){
        uksort($_params, 'strnatcmp');
        foreach ($_params as $key => $value){
            if(is_array($value)){
                $_params[$key] = sortArrayByKeyAsc($value);
            }
        }
    }
    return $_params;
}