0

I have an array:

array(1,'Test','Jonathan')

and id like to end up with:

array(1,'Jonathan','Test')

How do i accomplish this using PHP?

somejkuser
  • 8,856
  • 20
  • 64
  • 130
  • 1
    This resource is great: http://php.net/manual/en/array.sorting.php and `usort` in more complicated cases is a life-saver – Ofir Baruch May 18 '13 at 18:24

3 Answers3

3

One possible approach (demo):

$arr = array(10,'Foo', 'Abc', 5, 3.2, 'Test','Jonathan');
usort($arr, function($a, $b) {
  if (is_int($a) || is_float($a)) {
    if (is_int($b) || is_float($b)) {
      return $a - $b; 
    }
    else 
      return -1;
  }
  elseif (is_int($b) || is_float($b)) {
    return 1;
  }
  else {
    return strcmp($a, $b);
  }
});
print_r($arr);

Output:

Array
(
    [0] => 3.2
    [1] => 5
    [2] => 10
    [3] => Abc
    [4] => Foo
    [5] => Jonathan
    [6] => Test
)
raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • That's not working the way you think it's working. `is_float` is false for integers, so it's just comparing as strings. If you replace `10` with `1` in your Array, it will sort before `3`. – Mark Reed May 18 '13 at 18:33
2

use usort():

http://php.net/manual/en/function.usort.php

in your callback, process the cases separately: when both are numeric, when both are strings, and when one is numeric and the other is a string. Be wary of type conversions as you do.

Denis de Bernardy
  • 75,850
  • 13
  • 131
  • 154
0

As everyone agrees, whatever the solution is here it has to do with usort.

If your desired sort order is numbers first in ascending order then strings in ascending lexicographical order, one comparison that almost nails it is

function($a, $b) { return is_int($b) - is_int($a) ?: strnatcmp($a, $b); }

See it in action.

The problem with this is that if the input contains mixed input strings such as "User10" and "User2" it will not sort them lexicographically ("User2" will come first).

If you might have both floats and ints in the array (but not mixed input strings) then you can augment the above to read

return is_int($b) + is_float($b) - is_int($a) - is_float(a) ?: ...

If you can also have mixed input strings then you should probably accept that an one-liner is not a good idea. :-)

Jon
  • 428,835
  • 81
  • 738
  • 806