views:

27

answers:

2

Hello!

I have an array like this one:

$a = array("MA1" => 0, "MA10" => 1, "MA20" => 2, "MA5" => 3, "SM10" => 4, "SM8" => 5, "SM20" => 6, "SN33" => 7);

I want to sort it, that I will have the following order:

$a = array("MA1" => 0, "MA5" => 3, "MA10" => 1, "MA20" => 2, "SM8" => 5, "SM10" => 4, "SM20" => 6, "SN33" => 7);

So I need a order which is alphabetical within the first two chars and numeric of the rest. So I think I have to do this with

uksort($a, "cmp");

So I need a function like this:

function cmp($a, $b) {
    // ???
    return strcasecmp($a, $b);
}

How do I need to write the function so that the order will be right?

Thank you in advance & Best Regards.

+2  A: 

You can use built-in natural comparison function:

$a = array("MA1" => 0, "MA10" => 1, "MA20" => 2, "MA5" => 3, "SM10" => 4, "SM8" => 5, "SM20" => 6, "SN33" => 7);
uksort($a, "strnatcasecmp");
print_r($a);

The code above would produce following output:

Array
(
    [MA1] => 0
    [MA5] => 3
    [MA10] => 1
    [MA20] => 2
    [SM8] => 5
    [SM10] => 4
    [SM20] => 6
    [SN33] => 7
)
leafnode
A: 

This is not bullet proof but should work for the cases you mentioned. It could fail if you use leading zeros or use a pattern some other pattern.

<?php
    function custom_cmp($a, $b){
        preg_match("@([A-Z]+)([0-9]+)@", $a, $ma);
        preg_match("@([A-Z]+)([0-9]+)@", $b, $mb);
        // if string parts do not match then difference of string part is sufficient
        // if string parts are same then difference of numerical part is required
        return strcasecmp($ma[1], $mb[1])
            ? strcasecmp($ma[1], $mb[1])
            : (int)$ma[2] - (int)$mb[2];
    }
    $a = array(
        "MA1"  => 0,
        "MA10" => 1,
        "MA20" => 2,
        "MA5"  => 3,
        "SM10" => 4,
        "SM8"  => 5,
        "SM20" => 6,
        "SN33" => 7
    );
    print_r($a);
    uksort($a, "custom_cmp");
    print_r($a);
?>
Salman A