Manikandan Arunachalam
Manikandan Arunachalam

Reputation: 1500

PHP sorting array based on keys in the order as alphabet then numberic and then special chars

I have an array like below,

array(
   [!] = array(),
   [a] = array(),
   [.] = array(),
   [n] = array(),
   [3] = array(),
   [1] = array());

I need to sort this array as,

array(
   [a] = array(),
   [n] = array(),
   [1] = array(),
   [3] = array(),
   [!] = array(),
   [.] = array());

How to do this in php()?

Upvotes: 2

Views: 624

Answers (3)

Elias Van Ootegem
Elias Van Ootegem

Reputation: 76395

TL;TR

The shortest way (both in terms of code and, after some basic comparisons) is the code I suggest near the "Demo2" link below:

uksort($arr, function($a, $b)
{
    if (ctype_alnum("$a") === ctype_alnum("$b"))
        return $a > $b;
    return "$a" < "$b";
});

You can sort an array using the keys with the ksort function:

ksort($array, SORT_STRING);

The second argument is telling PHP to compare all the keys (including the numeric indexes) as strings (meaning an index like 3 will be treated as if it were '3'). This will give you an array where the keys are in ascending order. The order of the keys you show (all single characters) will be the same as their respective ASCII values (. is 46, a is 97 and so on). Seeing as you want to reverse the order, you'll have to use the array_reverse function:

$array = array_reverse($array, true);

Again, the second argument is telling PHP to preserve the keys, if not, the indexes will be reset, leaving you with a numerically indexed array.

You can skip the array_reverse call quite easily by using the uksortfunction. It works much the same way as ksort, but takes a callback function as a second argument, so you can sort by index, in descending order, too:

uksort($arr, function($a, $b)
{
    return "$a" < "$b";//added quotes to convert to strings
});

Demo

You will note that this places the '.' key in front of the '!' key. In fact, if both keys are of the same type (numeric, alpha), it would appear you want to sort them in ascending order, which you can do easily:

uksort($arr, function($a, $b)
{
    if (ctype_alnum("$a") === ctype_alnum("$b"))//both are alnums, sort ascending
        return $a > $b;//sort ascending
    return "$a" < "$b";//else sort descending
});

Demo2

If your PHP version doesn't support anonymous functions, you can define a function and pass its name as second argument, but really: you ought to upgrade:

function sortDesc($a, $b)
{
    if (ctype_alnum("$a") === ctype_alnum("$b"))
        return $a > $b;
    return (string) $a < "$b";//casting is valid, too... both do the same thing
}
uksort($array, 'sortDesc');

Upvotes: 2

Think Different
Think Different

Reputation: 2815

You can try:

<?php

    $arr = array(
               '!' => array(),
               'a' => array(),
               '.' => array(),
               'n' => array(),
               '3' => array(),
               '1' => array(),
               '$' => array(),
               '8' => array(),
               'm' => array(),
               'x' => array(),
               'c' => array(),
            );

    function mySort($arr){

        $keys = array_keys($arr);
        sort($keys);

        $result = array();
        $temp = array();
        foreach($keys as $key){
            if(!is_numeric($key) && !ctype_alpha($key)){
                $temp[$key] = $arr[$key];
            }else{
                $result[$key] = $arr[$key];
            }
        }
        foreach($temp as $k => $v){
            $result[$k] = $v;
        }
        return $result;

    }


    print_r(mySort($arr));


?>

Result:

Array
(
    [a] => Array()
    [c] => Array()
    [m] => Array()
    [n] => Array()
    [x] => Array()
    [1] => Array()
    [3] => Array()
    [8] => Array()
    [!] => Array()
    [$] => Array()
    [.] => Array()
)

Upvotes: 2

Nalin Singapuri
Nalin Singapuri

Reputation: 463

// function to sort the array keys with
function compare($a, $b)
{
    // Look for [A-z]
    if (ctype_alpha($a)) {
        if (ctype_alpha($b)) {
            return strcasecmp($a, $b);
        } else {
            return -1;
        }
    } elseif (ctype_alpha($b)) {
        return 1;
    }

    if (is_int($a)) {
        if (is_int($b)) {
            return $a > $b;
        } else {
            return -1;
        }
    } elseif (is_int($b)) {
        return 1;
    }

    return $a > $b;
}

$a = array(
   '!' => array(),
   'a' => array(),
   '.' => array(),
   'n' => array(),
   '3' => array(),
   '1' => array()
);

// use the function we defined above to sort the array.
uksort($a, "compare");

Upvotes: 2

Related Questions