php - uksort() - single digit integers being treated as larger than double digit integers when first integer is smaller -
as question suggests, i'm using uksort()
desired ordering multidimensional array.
everything's working great, exception of 1 small flaw. i'm having trouble conveying issue is, it's if natsort()
being applied somewhere , can't figure out.
here's uksort() callback:
uksort($loanprograms, function($a, $b){ $yeara = abs((int) filter_var($a, filter_sanitize_number_int)); $yearb = abs((int) filter_var($b, filter_sanitize_number_int)); return $yearb > $yeara ? 1 : -1; });
i'm extracting numbers string (which i've triple checked). numbers this:
$a - 30 $b - 5 $a - 20 $b - 10 $a - 30 $b - 15 $a - 7 $b - 10
however, issue 7
treated larger 10
, , 5
treated larger 30
...etc.
i can't figure out issue here. thoughts appreciated.
edit
snapshot of multi dimensional array:
array ( [conventional 15yr fixed] => array ( [0] => array ( [humanname] => conventional 15yr fixed [rate] => 2.875 ) ) [conventional 20yr fixed] => array ( [0] => array ( [humanname] => conventional 20yr fixed ) ) [conventional 7/1 arm] => array ( [0] => array ( [humanname] => conventional 7/1 arm ) …… )
the result give expected following reasons:
1. sorting descending:
return $yearb > $yeara ? 1 : -1;
to sort ascending, should switch 2 variables. see quote manual under next point.
2. don't treat equality:
the manual on uksort
says callback function (i highlight):
the comparison function must return integer less than, equal to, or greater zero if first argument considered respectively less than, equal to, or greater second.
for reason, better return numerical difference of 2 arguments. ascending sort be:
return $yeara - $yearb;
3. multiple digit groups joined
strings separated digit groups can give unexpected values: example "7/1" sanitized 71.
to resolve this, use strpbrk instead of filter_var:
function firstunsignedint($s) { return (int) strpbrk($s, "0123456789"); } uksort($loanprograms, function($a, $b){ // sort descending on first number in each string: return firstunsignedint($b) - firstunsignedint($a); });
you can see code run on eval.in.
alternative uksort
the array_multisort function allows sort array, applying same order change happens when sorting array of same size. use array extracted numerical values purpose:
function firstunsignedint($s) { return (int) strpbrk($s, "0123456789"); } // extract numbers keys new array: $terms = array_map('firstunsignedint', array_keys($loanprograms)); // sort numbers , let original array follow reordering: array_multisort($terms, sort_desc, $loanprograms);
you can see code run on eval.in.
this make debugging easier, have array extracted numbers readily available.
Comments
Post a Comment