我有一个这种形式的文件名数组:
“A - 1.2 - 平面图.PDF”
我需要首先按照开头的类别对数组进行排序,顺序如下:
1. Category: A
2. Category: ESC
3. Category: C
4. Category: M
5. Category: E
6. Category: P
然后我需要按类别后面的数字对数组进行排序。
以下是要排序的数组示例:
$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";
理想情况下,此数组将成为
$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";
我有以下正则表达式来正确分组文件名:
^([A-Z]+?) ?- ?([0-9]+)\.([0-9]+)(\.([0-9]+))?.*$
我希望数组按组1排序,然后按组2排序,然后按组3排序。如果组5存在,则按组排序。忽略组4.
按字典顺序对类别进行排序可能更容易。如果是这样,那就没问题;虽然如果它们按照上述顺序排序会更好。
有没有办法用PHP做到这一点?
答案 0 :(得分:5)
有一个sort函数,它将compare方法作为参数。您可以使用它,例如:
$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");
答案 1 :(得分:1)
怎么样:
$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";
function cmp($a,$b) {
$arr_a = split(' - ', $a);
$arr_b = split(' - ', $b);
if ($arr_a[0] == $arr_b[0])
return strcmp($arr_a[1], $arr_b[1]);
return strcmp($arr_a[0], $arr_b[0]);
}
usort($arr, "cmp");
print_r($arr);
<强>输出:强>
Array
(
[0] => A - 1.0 - Title Page.PDF
[1] => A - 1.2 - Floor Plan.PDF
[2] => A - 2.1.0 - Structural Details.PDF
[3] => A - 2.1.1 - Structural Details.PDF
[4] => A - 2.2 - Enlarged Floor Plans
[5] => C - 1.0 - Civil Title Page.PDF
[6] => E - 1.0 - Electrical Title Page.PDF
[7] => ESC - 1.0 - Erosion Control Plan.PDF
[8] => M - 1.0 - Mechanical Title Page.PDF
[9] => P - 1.0 - Plumbing Title Page.PDF
)
答案 2 :(得分:1)
将字符串分解成有意义的部分后,我感觉到一系列级联的三元表达式要比if
块更整齐,才能达到随后的平局条件。
此外,使用version_compare()
非常适合您的中间子字符串-这样可确保当您的主要/次要/微型版本移至两位数范围时,自然排序仍然有效。
使用use()
声明将您的自定义优先级数组传递到自定义函数得分中。
代码:(Demo)
$arr = [
"A - 1.0 - Title Page.PDF",
"A - 2.2 - Enlarged Floor Plans",
"A - 2.1.0 - Structural Details.PDF",
"E - 1.0 - Electrical Title Page.PDF",
"A - 1.2 - Floor Plan.PDF",
"P - 1.0 - Plumbing Title Page2.PDF",
"A - 2.1.1 - Structural Details.PDF",
"C - 1.0 - Civil Title Page.PDF",
"M - 1.0 - Mechanical Title Page.PDF",
"ESC - 1.0 - Erosion Control Plan.PDF",
"P - 1.0 - Plumbing Title Page.PDF",
];
$priorities = array_flip(['A', 'ESC', 'C', 'M', 'E', 'P']);
usort($arr, function ($a, $b) use ($priorities) {
[$categoryA, $versionA, $nameA] = explode(' - ', $a, 3);
[$categoryB, $versionB, $nameB] = explode(' - ', $b, 3);
return $priorities[$categoryA] <=> $priorities[$categoryB] // priorities as first criteria
?: version_compare($versionB, $versionA) // then descending versions as second criteria
?: $nameA <=> $nameB; // then compare names ascending
});
var_export($arr);
输出:
array (
0 => 'A - 2.2 - Enlarged Floor Plans',
1 => 'A - 2.1.1 - Structural Details.PDF',
2 => 'A - 2.1.0 - Structural Details.PDF',
3 => 'A - 1.2 - Floor Plan.PDF',
4 => 'A - 1.0 - Title Page.PDF',
5 => 'ESC - 1.0 - Erosion Control Plan.PDF',
6 => 'C - 1.0 - Civil Title Page.PDF',
7 => 'M - 1.0 - Mechanical Title Page.PDF',
8 => 'E - 1.0 - Electrical Title Page.PDF',
9 => 'P - 1.0 - Plumbing Title Page.PDF',
10 => 'P - 1.0 - Plumbing Title Page2.PDF',
)
或者,您可以在平衡阵列上使用单个太空飞船操作员比较,以获得完全相同的效果:(Demo)
usort($arr, function ($a, $b) use ($priorities) {
[$categoryA, $versionA, $nameA] = explode(' - ', $a, 3);
[$categoryB, $versionB, $nameB] = explode(' - ', $b, 3);
return [$priorities[$categoryA], version_compare($versionB, $versionA), $nameA]
<=>
[$priorities[$categoryB], version_compare($versionA, $versionB), $nameB];
});
我相信第一个摘要的好处是,除非达成,否则不会执行随后的决胜局。无论是否需要比较,第二个代码段都将填充所有元素。如果这是不正确的,欢迎任何人通过评论对我进行纠正。