Sort an array of alphabetic and numeric string-type elements ASC, but with numeric elements after alphabetic elements
Asked Answered
S

5

16

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.

Shephard answered 25/9, 2012 at 19:45 Comment(2)
you can try dividing the array into two: strings and integers solely, then apply sort, and then merge them together.Manifestation
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 needShephard
A
15

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' );
Amero answered 25/9, 2012 at 19:55 Comment(0)
B
7

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
)
Babu answered 25/9, 2012 at 19:53 Comment(0)
P
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);
Pasteurization answered 25/9, 2012 at 19:54 Comment(0)
O
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

Orling answered 25/9, 2012 at 19:59 Comment(0)
B
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);
Baptism answered 22/9, 2022 at 5:20 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.