Search code examples
phpstringsortingcustom-sort

Sort characters in string giving priority by lower-case, then upper-case, then numbers then symbols


I am new to PHP and trying to do programming questions that involve sorting. I want to solve this problem in which the input and output are as followed.

Before Sort: 6Ata7~58jh&*(*HLy^)&a[yjJ>8]G8,$9<Y;B:%^

After Sort: jhytaayjYBJGAHL8968758~&*(*^)&[>],$<;:%^

I need help understanding how to sort according to the order state mention in the title and how I can get the same result from the above input and output. Below is the code I'm working on:

function reverseString($string){
    $stringlen = strlen($string) - 1;
    $split_str = str_split($string, 1);

    $array = array();

    for($i = 0; $i <= $stringlen; $i++){
        array_push($array, $split_str[$i]);
    }

    rsort($array, SORT_STRING | SORT_NUMERIC | SORT_FLAG_CASE | SORT_NATURAL);

    return $array;
}

if(isset($_POST['input']) && !empty($_POST['input'])){
    echo '<pre>';
    echo 'Before sort: ';
    print_r($_POST['input']);
    echo '<br>--------------------<br>';
    echo 'After sort:' ;
    print_r(reverseString($_POST['input'])); 
    echo '</pre>';
}

Solution

  • One option would be to sort the array of string characters using a lambda function. We can use usort() on the array, with a helper function get_rank() returning a value, from 1 to 4, depending on whether the character be lowercase, uppercase, numeric, or anything else (including symbols).

    function get_rank($letter) {
        if (ctype_lower($letter)) {
            return 1;
        }
        else if (ctype_upper($letter)) {
            return 2;
        }
        else if (is_numeric($letter)) {
            return 3;    
        }
        else {
            return 4;
        }
    }
    
    $input = "6Ata7~58jh&*(*HLy^)&a[yjJ>8]G8,$9<Y;B:%^";
    echo $input . "\n";
    $letters = str_split($input);
    usort($letters, function($a, $b) {
        return get_rank($a) > get_rank($b);
    });
    $output = implode("", $letters);
    echo $output;
    

    This prints:

    6Ata7~58jh&*(*HLy^)&a[yjJ>8]G8,$9<Y;B:%^
    ajyjhatyYBAGJHL9886875,%:;~<$&)&]*>(*^[^
    

    Note that you didn't specify any logic for sorting within groups of lowercase, symbols, etc. The above logic can be modified to include this.