stemie
stemie

Reputation: 779

Sort array based on the numbers and a certain piece of text that occurs within a string

I have an array which I got from a directory with pdf files in it using scandir

$array = array(7) { 
    [0]=> string(17) "q150824-spost.pdf" 
    [1]=> string(17) "s150826-spost.pdf" 
    [2]=> string(16) "s150826-spro.pdf" 
    [3]=> string(17) "t150827-spost.pdf" 
    [4]=> string(16) "t150827-spro.pdf" 
    [5]=> string(17) "v150825-spost.pdf" 
    [6]=> string(16) "v150825-spro.pdf" 
}

I need to sort the array by the numbers in the file name (eg. 150824 which is actually a date) which I can do using the following:

usort($array, function($a, $b) {
  return filter_var($a, FILTER_SANITIZE_NUMBER_INT) - filter_var($b, FILTER_SANITIZE_NUMBER_INT);
});

The above gives me an array sorted by the numbers (which is almost what I want):

$array = array(7) { 
    [0]=> string(17) "q150824-spost.pdf" 
    [1]=> string(17) "v150825-spost.pdf" 
    [2]=> string(16) "v150825-spro.pdf" 
    [3]=> string(16) "s150826-spro.pdf" 
    [4]=> string(17) "s150826-spost.pdf" 
    [5]=> string(17) "t150827-spost.pdf" 
    [6]=> string(16) "t150827-spro.pdf" 
}

However, in addition to this I would also like to sort alphabetically by spost and spro (the text before .pdf) I'm at a loss as to how to achieve this though?

If two strings in the array have the same numbers/date (eg. 150826) I want to then sort by spost first and then spro.

Upvotes: 1

Views: 28

Answers (2)

Rizier123
Rizier123

Reputation: 59691

This should work for you:

First just grab the number and the topic name out of the file name with preg_match_all() and assign it to the variables. After this simply sort it by the topic, if the numbers are equal, otherwise by the numbers.

<?php


    usort($arr, function($a, $b){
        preg_match_all("/^\w(\d+)-(\w+)/", $a, $mA);
        preg_match_all("/^\w(\d+)-(\w+)/", $b, $mB);

        $numberA = $mA[1][0];
        $numberB = $mB[1][0];

        $topicA = $mA[2][0];
        $topicB = $mB[2][0];

        if($numberA == $numberB){
            return strcmp($topicA, $topicB);
        }

        return $numberA > $numberB ? 1 : -1;

    });


    print_r($arr);

?>

output:

Array
(
    [0] => q150824-spost.pdf
    [1] => v150825-spost.pdf
    [2] => v150825-spro.pdf
    [3] => s150826-spost.pdf
    [4] => s150826-spro.pdf
    [5] => t150827-spost.pdf
    [6] => t150827-spro.pdf
)

Upvotes: 1

Sam
Sam

Reputation: 2970

Actually you can just do the following

$array =[
    "q150824-spost.pdf",
    "s150826-spost.pdf",
    "s150826-spro.pdf",
    "t150827-spost.pdf",
    "t150827-spro.pdf",
    "v150825-spost.pdf",
    "v150825-spro.pdf",
];

usort($array, function($a, $b) {
    return filter_var($a, FILTER_SANITIZE_NUMBER_INT) - filter_var($b, FILTER_SANITIZE_NUMBER_INT) + (strlen($b) > strlen($a) ? 1 : 0);
});

print_r($array);

Output

Array
(
    [0] => q150824-spost.pdf
    [1] => v150825-spost.pdf
    [2] => v150825-spro.pdf
    [3] => s150826-spost.pdf
    [4] => s150826-spro.pdf
    [5] => t150827-spost.pdf
    [6] => t150827-spro.pdf
)

It is sort by spost first and then spro

Upvotes: 1

Related Questions