Elmer
Elmer

Reputation: 259

Sort php Array by integers inside values

I'm trying to sort an array numerically but the integers are found in the middle of a value, not on the first character. Here is what my array looks like (using dummy values):

$array = Array('A25','A30','A40','B25','B30','B40','AB25','AB30','AB40');

sort($array,1);

Output after foreach:

A25
A30
A40

AB25
AB30
AB40

B25
B30
B40

Expected output:

A25
AB25
B25

A30
AB30
B30

A40
AB40
B40

What would be the best sorting method for this? Really appreciate it, thanks!

Upvotes: 0

Views: 153

Answers (5)

Mischa
Mischa

Reputation: 99

U can use various kinds of ways to sort arrays in PHP. PHP has some good ways build in to do sorting on arrays. In this case I agree with Mark Baker, however I would recommend a preg_replace to get the numeric value of your strings.

$array = Array('A25','A30','A40','B25','B30','B40','AB25','AB30','AB40');
function cmp($a, $b)
{
    $v1 = preg_replace("/[^0-9]/", "", $a);
    $v2 = preg_replace("/[^0-9]/", "", $b);
    if ($v1 == $v2) {
        return 0;
    }
    return ($v1 < $v2) ? -1 : 1;
}
usort($array, "cmp");
var_dump($array);

Look into the PHP information about sorting arrays, php.net/usort and various others.

Upvotes: 0

Andrew
Andrew

Reputation: 5340

Here's a stable sort, the result is: "A25" "B25" "AB25" "A30" "B30" "AB30" "A40" "B40" "AB40" .

function getNum($str)
{
    preg_match ( '/(\d+)$/', $str, $match );

    return intval ( $match [1] );
}

function stableSort($arr)
{
    $newArr = array ();

    foreach ( $arr as $idx => $ele )
    {
        $newArr [] = array (
                'idx' => $idx,
                'val' => $ele 
        );
    }

    usort ( $newArr, 
            function ($a, $b)
            {
                $d = getNum ( $a ['val'] ) - getNum ( $b ['val'] );
                return $d ? $d : $a ['idx'] - $b ['idx'];
            } );

    $sortArr = array ();

    foreach ( $newArr as $ele )
    {

        $sortArr [] = $ele ['val'];
    }

    return $sortArr;
}

var_dump ( stableSort ( $array ) );

Upvotes: 0

rakeshjain
rakeshjain

Reputation: 1761

You can use user defined function with usort to achieve it

<?php

function mySort($a,$b) {
    $numA = '';
    $strA = '';
    $numB = '';
    $strB = '';
    for($i=0;$i<strlen($a); $i++) { 
        if(is_numeric($a[$i])) {
            $numA .= (string)$a[$i];
        }
        else {
            $strA .= $a[$i];
        }
    }
    for($i=0;$i<strlen($b); $i++) {
        if(is_numeric($b[$i])) {
            $numB .= (string)$b[$i];
        }
        else {
            $strB .= $b[$i];
        }
    }
    $numA = (int)$numA;
    $numB = (int)$numB;
    if($numA>$numB) {
        return true;
    }
    elseif($numA<$numB) {
        return false;
    }
    else {
        if(strcmp($strA,$strB)>0) {
            return true;
        }
        else {
            return false;
        }
    }
}

$array = Array('A25','A30','A40','B25','B30','B40','AB25','AB30','AB40');
var_dump($array);
usort($array,'mySort');
var_dump($array);
?>

Upvotes: 0

rsakhale
rsakhale

Reputation: 1036

Have created a custom function depending on your requirement, please see below code

<?php

$array = array('A30','A25','ZZZ','A40','Rohan','B25','B30','Sakhale','B40','AB25','AB30','AB40');
$array = sortArrayByNumber($array);

var_dump($array);

/**
 *  @name sortArrayByNumber
 *  @abstract sort the entire array irrespective of the string, but the numbers into it
 *              also we append the elements not having any number at the end
 *  @author Rohan Sakhale
 */
function sortArrayByNumber($arr){
    $sortedArr = array();
    $tempArray = array();
    $stringOnlyArray = array();
    foreach($arr as $v){
        $num = getNumberFromString($v);
        /**
         *  If no number found, append it into stringOnlyArray
         */
        if($num == ''){
            $stringOnlyArray[] = $v;
            continue;
        }
        if(!isset($tempArray[$num])){
            $tempArray[$num] = array();
        }
        $tempArray[$num][] = $v;
    }
    $tempArrayKeys = array_keys($tempArray);
    sort($tempArrayKeys);
    foreach($tempArrayKeys as $key){
    sort($tempArray[$key]);
        $sortedArr = array_merge($sortedArr, $tempArray[$key]);
    }
    if(count($stringOnlyArray) > 0){
        sort($stringOnlyArray);
        $sortedArr = array_merge($sortedArr, $stringOnlyArray);
    }
    return $sortedArr;
}

/**
 *  @str - String param which tend to have number
 */
function getNumberFromString($str){
    $matches = null;
    preg_match_all('!\d+!', $str, $matches);
    if(!is_null($matches) and is_array($matches)){
        if(isset($matches[0][0])){
            return $matches[0][0];
        }
    }
    return '';
}

?>

Here sort by number method is trying to firstly identify the number's in your string and maintain a separate array of it based on the keys, later we sort in ascending order every key's of number and then we finally merge it into sorted array

Upvotes: 0

Mark Baker
Mark Baker

Reputation: 212452

$array = Array('A25','A30','A40','B25','B30','B40','AB25','AB30','AB40');
usort(
    $array,
    function($a, $b) {
        list($achar,$anum) = sscanf($a, '%[A-Z]%d');
        list($bchar,$bnum) = sscanf($b, '%[A-Z]%d');
        if ($anum > $bnum) {
            return 1;
        } elseif (($anum == $bnum) && ($achar > $bchar)) { 
            return 1;
        }
        return -1;
    }
);

var_dump($array);

Upvotes: 3

Related Questions