I have an array of filenames of this form:
"A - 1.2 - Floor Plan.PDF"
I need to sort the array first by the category at the beginning, in the following order:
1. Category: A
2. Category: ESC
3. Category: C
4. Category: M
5. Category: E
6. Category: P
Then I need to sort the array by the numbers following the category.
Here's an example of the array to be sorted:
$arr[0] = "A - 1.0 - Title Page.PDF";
$arr[1] = "A - 2.2 - Enlarged Floor Plans";
$arr[2] = "A - 2.1.0 - Structural Details.PDF";
$arr[3] = "E - 1.0 - Electrical Title Page.PDF";
$arr[4] = "A - 1.2 - Floor Plan.PDF";
$arr[5] = "P - 1.0 - Plumbing Title Page.PDF";
$arr[6] = "A - 2.1.1 - Structural Details.PDF";
$arr[7] = "C - 1.0 - Civil Title Page.PDF";
$arr[8] = "M - 1.0 - Mechanical Title Page.PDF";
$arr[9] = "ESC - 1.0 - Erosion Control Plan.PDF";
Ideally, this array would then become
$arr[0] = "A - 1.0 - Title Page.PDF";
$arr[1] = "A - 1.2 - Floor Plan.PDF";
$arr[2] = "A - 2.1.0 - Structural Details.PDF";
$arr[3] = "A - 2.1.1 - Structural Details.PDF";
$arr[4] = "A - 2.2 - Enlarged Floor Plans";
$arr[5] = "ESC - 1.0 - Erosion Control Plan.PDF";
$arr[6] = "C - 1.0 - Civil Title Page.PDF";
$arr[7] = "M - 1.0 - Mechanical Title Page.PDF";
$arr[8] = "E - 1.0 - Electrical Title Page.PDF";
$arr[9] = "P - 1.0 - Plumbing Title Page.PDF";
I have the following regular expression for grouping the file names appropriately:
^([A-Z]+?) ?- ?([0-9]+)\.([0-9]+)(\.([0-9]+))?.*$
I want the array sorted by group 1, then by group 2, then by group 3. If Group 5 exists, then sort last by group 5. Ignore group 4.
It may be easier to sort the categories lexicographically. If so, that would be alright; though it would be preferable if they were sorted in the order mentioned above.
Is there any way to do this with PHP?
There is sort function which takes compare method as an argument. You can use it for example like this:
$order = array('A', 'ESC', 'C', 'M', 'E', 'P'); // order of categories
$order = array_flip($order); // flip order array, it'll look like: ('A'=>0, 'ESC'=>1, ...)
function cmp($a, $b)
{
global $order;
$ma = array();
$mb = array();
preg_match('/^([A-Z]+?) ?- ?([0-9]+)\.([0-9]+)(?:\.([0-9]+))?.*$/', $a, $ma);
preg_match('/^([A-Z]+?) ?- ?([0-9]+)\.([0-9]+)(?:\.([0-9]+))?.*$/', $b, $mb);
if ($ma[1] != $mb[1]) {
return ($order[$ma[1]] < $order[$mb[1]]) ? -1 : 1;
}
if ($ma[2] != $mb[2]) {
return $ma[2] < $mb[2] ? -1 : 1;
}
if ($ma[3] != $mb[3]) {
return $ma[3] < $mb[3] ? -1 : 1;
}
// I've changed a regex a little bit, so the last number is 4th group now
if (@$ma[4] != @$mb[4]) {
return @$ma[4] < @$mb[4] ? -1 : 1;
}
return 0;
}
usort($arr, "cmp");