17

I have an array of values which are either all-letters or all-numbers and need to sort them in an ascending fashion. Additionally, I want all-numeric values to be moved to the end of the array so that they occur after all of the non-numeric values.

$test = ["def", "yz", "abc", "jkl", "123", "789", "stu"];

If I run sort() on it I get:

Array
(
    [0] => 123
    [1] => 789
    [2] => abc
    [3] => def
    [4] => jkl
    [5] => stu
    [6] => yz
)

but I'd like to see:

Array
(
    [0] => abc
    [1] => def
    [2] => jkl
    [3] => stu
    [4] => yz
    [5] => 123
    [6] => 789
)

I tried array_reverse(), but that didn't seem to change anything. I'm at a loss for how to get the numbers last, but in ascending order.

2
  • you can try dividing the array into two: strings and integers solely, then apply sort, and then merge them together. Commented Sep 25, 2012 at 19:53
  • Lots of good answers, was hoping for a simple function like sort() but, I guess overall the answers below make sense. Thank you all, I will give them a shot, and come back with which one works best for my need Commented Sep 25, 2012 at 20:01

5 Answers 5

16

What you need is sort but with a custom comparison function (usort). The following code will get it done:

function myComparison($a, $b){
    if(is_numeric($a) && !is_numeric($b))
        return 1;
    else if(!is_numeric($a) && is_numeric($b))
        return -1;
    else
        return ($a < $b) ? -1 : 1;
} 
$test = array("def", "yz", "abc", "jkl", "123", "789", "stu");
usort ( $test , 'myComparison' );
Sign up to request clarification or add additional context in comments.

Comments

8

You could convert your numbers to integers before sorting:

$array = array("def", "yz", "abc", "jkl", "123", "789", "stu");

foreach ($array as $key => $value) {
    if (ctype_digit($value)) {
        $array[$key] = intval($value);
    }
}

sort($array);
print_r($array);

Output:

Array
(
  [0] => abc
  [1] => def
  [2] => jkl
  [3] => stu
  [4] => yz
  [5] => 123
  [6] => 789
)

Comments

2

In the following code is separate the data in two arrays: one is numerical the other is not and sort it and merge it.

$arr1 = $arr2 = array();

$foreach ($arr as $val) {

if (is_numeric($val)) {array_push($arr2, $val); } 
else {array_push($arr1, $val);}

} 

so you have to separate arrays whit numeric and non-numeric

sort($arr2);
sort($arr1);

$test = array_merge($arr2,$arr1);

Comments

1

You could do this using usort and a custom comparison function, but this sounds like more trouble than it's worth. I'd use sort, and then handle that output accordingly. It's not clear how you want to use it, but a simple way might be:

sort($test);
foreach ($test as $index=>$value) {
    if (is_numeric($value)) {
       $test[] = $value;
       unset($test[$index]);
    } else {
        continue;
    }
}

usort will probably be faster and it's going to do the comparisions once, while the other solutions mentioned thus far may be a little slower as they require iterating over some or all of the array before or after the sort

Comments

1

You do not need to engage any iterated processing for this task -- and therefore should not.

Use array_multisort() to sort the array numerically, then as strings (normally).

Code: (Demo)

array_multisort($test, SORT_NUMERIC, $test);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.