4

Having trouble finding the correct function to sort a multi dimensional array as follows:

Array(    [0] => Array      (
             [username]    => 123           
             [name]        => Name    
             [address]     => array  (
                                 [line1]    => address line 1
                                 [line2]    => address line 2
                                 [postcode] => postcode
                            ),
         [1] => Array      (
             [username]    => 1234           
             [name]        => Name    
             [address]     => array  (
                                 [line1]    => address line 1
                                 [line2]    => address line 2
                                 [postcode] => postcode
                            )
)

I wish to sort the above array by an element in the address array().

I am aware of the array_multisort function which will quite easily sort by either username, or address but just cant figure out how to sort using a field another level down.

Any help would be much appreciated

Thanks

user2280745
  • 81
  • 1
  • 5

3 Answers3

4

Just figured how to achieve it...

First need to extract the data we want to sort into a seperate array before sending it to the array_multisort() function

Example:

 foreach(Array() as $key=>$value) {
     $sort_data[$key] = $value['address']['postcode'];
}

array_multisort($sort_data, SORT_DESC, Array());

The initial Array() will now be sorted based on the postcode value and whatever SORT filter was provided to the array_multisort() function.

user2280745
  • 81
  • 1
  • 5
2

With this solution you don't need to make additional preparations to get a result:

$result = usort($data, function($a, $b) {
    return strcmp($a['address']['postcode'], $b['address']['postcode']);
});

array_multisort purpose is to sort multiple different arrays at once. If there is only one original array to be sorted - usort() should be used.

deceze
  • 510,633
  • 85
  • 743
  • 889
zerkms
  • 249,484
  • 69
  • 436
  • 539
0

FYI, To support both string and numeric sorting usort ends up being approx 10 times slower.

$rs[] = array('username'=>'bla bla..','Logins'=>124);
$rs[] ...

usort($rs,function($a,$b) {
  $i = 'Logins';
  if (is_numeric($a[$i])) {
    return $a[$i] > $b[$i];
  } else {
    return strcmp($a[$i],$b[$i]);
  }
});

vs.

$orderBy = 'Logins';
$sort = array();
foreach($rs as $key=>$rec) $sort[$key] = $rec[$orderBy];
array_multisort($sort,SORT_ASC,$rs);

demo

<?php
$rs = array();
$rs[] = array('adam','cederblom',50);
$rs[] = array('denny','bengtsson',9);
$rs[] = array('beata','andersson',30);
$rs[] = array('adam','cederblom',50);
$rs[] = array('denny','bengtsson',9);
$rs[] = array('beata','andersson',30);
$rs[] = array('adam','cederblom',50);
$rs[] = array('denny','bengtsson',9);
$rs[] = array('beata','andersson',30);
$rs[] = array('adam','cederblom',50);
$rs[] = array('denny','bengtsson',9);
$rs[] = array('beata','andersson',30);
$data = array_merge($rs,$rs);

$orderBy = 2; //0 - 2
//please note that usort doesn't use global, so update $i

echo 'Usort: ';
$start = microtime(true);
for($j=0;$j<1000;$j++) {
  //revert to unsorted.
  $rs = $data;
  usort($rs,function($a,$b) {
    $i = 2; //should be same as orderBy..
    if (is_numeric($a[$i])) {
      return $a[$i] > $b[$i];
    } else {
      return strcmp($a[$i],$b[$i]);
    }
  });
}
echo microtime(true) - $start . '<hr/>';
foreach($rs as $rec) {
  echo serialize($rec) . '<hr/>';
}

echo 'Multisort: ';
$start = microtime(true);
for($j=0;$j<1000;$j++) {
  //revert to unsorted.
  $rs = $data;
  $sort = array();
  foreach($rs as $key=>$rec) {
    //demo, numeric index in record
    $sort[$key] = $rec[$orderBy];
  }
  array_multisort($sort,SORT_ASC,$rs);
}
echo microtime(true) - $start . '<hr/>';
foreach($rs as $rec) {
  echo serialize($rec) . '<hr/>';
}
Teson
  • 6,644
  • 8
  • 46
  • 69