根据比较关联键的多个规则对每行中的元素进行排序
Sort elements in each row based on multiple rules comparing associative keys
我有一个多维数组,想按自定义顺序按键对它的子数组进行排序,其中我有一些固定位置和一些相对位置。
数组如下所示:
$array = [
[
"ARRIVAL" => '2022-03-08',
"INFO" => "TEST",
"V1_PROZ_WET" => 7,
"V1_ABS_WET" => 200,
"V1_PROZ" => 4,
"V1_ABS" => 150,
"V2_PROZ_WET" => 10,
"V2_ABS_WET" => 250,
"V2_PROZ" => 5,
"V2_ABS" => 180,
"BEZ" => "TEST",
"WET_TOTAL" => 500,
"DRY_TOTAL" => 300
],
[
"ARRIVAL" => '2022-03-07',
"INFO" => "TEST",
"V1_PROZ_WET" => 7,
"V1_ABS_WET" => 200,
"V1_PROZ" => 4,
"V1_ABS" => 150,
"V2_PROZ_WET" => 10,
"V2_ABS_WET" => 250,
"V2_PROZ" => 5,
"V2_ABS" => 180,
"BEZ" => "TEST",
"WET_TOTAL" => 500,
"DRY_TOTAL" => 300
],
[
"ARRIVAL" => '2022-03-06',
"INFO" => "TEST",
"V1_PROZ_WET" => 7,
"V1_ABS_WET" => 200,
"V1_PROZ" => 4,
"V1_ABS" => 150,
"V2_PROZ_WET" => 10,
"V2_ABS_WET" => 250,
"V2_PROZ" => 5,
"V2_ABS" => 180,
"BEZ" => "TEST",
"WET_TOTAL" => 500,
"DRY_TOTAL" => 300
],
];
我想按以下顺序排序:
$sortOrder = [
"INFO", //fixed pos 1
"BEZ", //fixed pos 2
"WET_TOTAL", //fixed pos 3
"DRY_TOTAL", //fixed pos 4
"_PROZ", //all dry percentage values
"_ABS", //all dry abs values
"_PROZ_WET", //all wet percentage values
"_ABS_WET" //all wet abs values
];
子数组的预期输出为:
[
"INFO" => "TEST",
"BEZ" => "TEST",
"WET_TOTAL" => 500,
"DRY_TOTAL" => 300,
"V1_PROZ" => 4,
"V2_PROZ" => 5,
"V1_ABS" => 150,
"V2_ABS" => 180,
"V1_PROZ_WET" => 7,
"V2_PROZ_WET" => 10,
"V1_ABS_WET" => 200,
"V2_ABS_WET" => 250,
"ARRIVAL" => '2022-03-06'
]
我看到 PHP 的 usort 能够执行自定义排序功能,但我被卡住了,因为我无法获得它 运行.
这个 SO-Answer 给了我一些关于如何对多维数组进行自定义排序的很好的输入,但我需要通过键对它们进行排序并且没有我可以随时查看的“id”键在
这里是一个fiddle的游乐场。
在每一行调用 uksort()
时迭代 modify-by-reference。
使用 Elvis 运算符回退到优先级较低的标准。
如果您的 PHP 版本还没有提供箭头函数,您需要调整脚本以使用 long-handed 函数语法。
如果您的 PHP 版本尚未提供 str_contains()
,您需要将这些调用换成 long-winded strpos() !== false
检查。
这种 boolean-based 排序算法可以欺骗不熟悉排序的开发人员。当飞船运算符比较两个布尔值时,它将 false
视为 0
,将 true
视为 1
。换句话说,如果您使用 ASC 排序,则 false
记录排在 true
记录之前。如果你想要相反的排序方向,那么你交换表达式中 $a
和 $b
的位置。 $b <=> $a
表示降序排列。
代码:(Demo)
foreach ($array as &$row) {
uksort($row, fn($a, $b) =>
($b === 'INFO') <=> ($a === 'INFO')
?: ($b === 'BEZ') <=> ($a === 'BEZ')
?: ($b === 'WET_TOTAL') <=> ($a === 'WET_TOTAL')
?: ($b === 'DRY_TOTAL') <=> ($a === 'DRY_TOTAL')
?: ($a === 'ARRIVAL') <=> ($b === 'ARRIVAL')
?: str_contains($a, '_WET') <=> str_contains($b, '_WET')
?: str_contains($b, '_PROZ') <=> str_contains($a, '_PROZ')
?: str_contains($b, '_ABS') <=> str_contains($a, '_ABS')
?: $a <=> $b
);
}
var_export($array);
输出:
array (
0 =>
array (
'INFO' => 'TEST',
'BEZ' => 'TEST',
'WET_TOTAL' => 500,
'DRY_TOTAL' => 300,
'V1_PROZ' => 4,
'V2_PROZ' => 5,
'V1_ABS' => 150,
'V2_ABS' => 180,
'V1_PROZ_WET' => 7,
'V2_PROZ_WET' => 10,
'V1_ABS_WET' => 200,
'V2_ABS_WET' => 250,
'ARRIVAL' => '2022-03-08',
),
1 =>
array (
'INFO' => 'TEST',
'BEZ' => 'TEST',
'WET_TOTAL' => 500,
'DRY_TOTAL' => 300,
'V1_PROZ' => 4,
'V2_PROZ' => 5,
'V1_ABS' => 150,
'V2_ABS' => 180,
'V1_PROZ_WET' => 7,
'V2_PROZ_WET' => 10,
'V1_ABS_WET' => 200,
'V2_ABS_WET' => 250,
'ARRIVAL' => '2022-03-07',
),
2 =>
array (
'INFO' => 'TEST',
'BEZ' => 'TEST',
'WET_TOTAL' => 500,
'DRY_TOTAL' => 300,
'V1_PROZ' => 4,
'V2_PROZ' => 5,
'V1_ABS' => 150,
'V2_ABS' => 180,
'V1_PROZ_WET' => 7,
'V2_PROZ_WET' => 10,
'V1_ABS_WET' => 200,
'V2_ABS_WET' => 250,
'ARRIVAL' => '2022-03-06',
),
)
我有一个多维数组,想按自定义顺序按键对它的子数组进行排序,其中我有一些固定位置和一些相对位置。
数组如下所示:
$array = [
[
"ARRIVAL" => '2022-03-08',
"INFO" => "TEST",
"V1_PROZ_WET" => 7,
"V1_ABS_WET" => 200,
"V1_PROZ" => 4,
"V1_ABS" => 150,
"V2_PROZ_WET" => 10,
"V2_ABS_WET" => 250,
"V2_PROZ" => 5,
"V2_ABS" => 180,
"BEZ" => "TEST",
"WET_TOTAL" => 500,
"DRY_TOTAL" => 300
],
[
"ARRIVAL" => '2022-03-07',
"INFO" => "TEST",
"V1_PROZ_WET" => 7,
"V1_ABS_WET" => 200,
"V1_PROZ" => 4,
"V1_ABS" => 150,
"V2_PROZ_WET" => 10,
"V2_ABS_WET" => 250,
"V2_PROZ" => 5,
"V2_ABS" => 180,
"BEZ" => "TEST",
"WET_TOTAL" => 500,
"DRY_TOTAL" => 300
],
[
"ARRIVAL" => '2022-03-06',
"INFO" => "TEST",
"V1_PROZ_WET" => 7,
"V1_ABS_WET" => 200,
"V1_PROZ" => 4,
"V1_ABS" => 150,
"V2_PROZ_WET" => 10,
"V2_ABS_WET" => 250,
"V2_PROZ" => 5,
"V2_ABS" => 180,
"BEZ" => "TEST",
"WET_TOTAL" => 500,
"DRY_TOTAL" => 300
],
];
我想按以下顺序排序:
$sortOrder = [
"INFO", //fixed pos 1
"BEZ", //fixed pos 2
"WET_TOTAL", //fixed pos 3
"DRY_TOTAL", //fixed pos 4
"_PROZ", //all dry percentage values
"_ABS", //all dry abs values
"_PROZ_WET", //all wet percentage values
"_ABS_WET" //all wet abs values
];
子数组的预期输出为:
[
"INFO" => "TEST",
"BEZ" => "TEST",
"WET_TOTAL" => 500,
"DRY_TOTAL" => 300,
"V1_PROZ" => 4,
"V2_PROZ" => 5,
"V1_ABS" => 150,
"V2_ABS" => 180,
"V1_PROZ_WET" => 7,
"V2_PROZ_WET" => 10,
"V1_ABS_WET" => 200,
"V2_ABS_WET" => 250,
"ARRIVAL" => '2022-03-06'
]
我看到 PHP 的 usort 能够执行自定义排序功能,但我被卡住了,因为我无法获得它 运行.
这个 SO-Answer 给了我一些关于如何对多维数组进行自定义排序的很好的输入,但我需要通过键对它们进行排序并且没有我可以随时查看的“id”键在
这里是一个fiddle的游乐场。
在每一行调用 uksort()
时迭代 modify-by-reference。
使用 Elvis 运算符回退到优先级较低的标准。
如果您的 PHP 版本还没有提供箭头函数,您需要调整脚本以使用 long-handed 函数语法。
如果您的 PHP 版本尚未提供 str_contains()
,您需要将这些调用换成 long-winded strpos() !== false
检查。
这种 boolean-based 排序算法可以欺骗不熟悉排序的开发人员。当飞船运算符比较两个布尔值时,它将 false
视为 0
,将 true
视为 1
。换句话说,如果您使用 ASC 排序,则 false
记录排在 true
记录之前。如果你想要相反的排序方向,那么你交换表达式中 $a
和 $b
的位置。 $b <=> $a
表示降序排列。
代码:(Demo)
foreach ($array as &$row) {
uksort($row, fn($a, $b) =>
($b === 'INFO') <=> ($a === 'INFO')
?: ($b === 'BEZ') <=> ($a === 'BEZ')
?: ($b === 'WET_TOTAL') <=> ($a === 'WET_TOTAL')
?: ($b === 'DRY_TOTAL') <=> ($a === 'DRY_TOTAL')
?: ($a === 'ARRIVAL') <=> ($b === 'ARRIVAL')
?: str_contains($a, '_WET') <=> str_contains($b, '_WET')
?: str_contains($b, '_PROZ') <=> str_contains($a, '_PROZ')
?: str_contains($b, '_ABS') <=> str_contains($a, '_ABS')
?: $a <=> $b
);
}
var_export($array);
输出:
array (
0 =>
array (
'INFO' => 'TEST',
'BEZ' => 'TEST',
'WET_TOTAL' => 500,
'DRY_TOTAL' => 300,
'V1_PROZ' => 4,
'V2_PROZ' => 5,
'V1_ABS' => 150,
'V2_ABS' => 180,
'V1_PROZ_WET' => 7,
'V2_PROZ_WET' => 10,
'V1_ABS_WET' => 200,
'V2_ABS_WET' => 250,
'ARRIVAL' => '2022-03-08',
),
1 =>
array (
'INFO' => 'TEST',
'BEZ' => 'TEST',
'WET_TOTAL' => 500,
'DRY_TOTAL' => 300,
'V1_PROZ' => 4,
'V2_PROZ' => 5,
'V1_ABS' => 150,
'V2_ABS' => 180,
'V1_PROZ_WET' => 7,
'V2_PROZ_WET' => 10,
'V1_ABS_WET' => 200,
'V2_ABS_WET' => 250,
'ARRIVAL' => '2022-03-07',
),
2 =>
array (
'INFO' => 'TEST',
'BEZ' => 'TEST',
'WET_TOTAL' => 500,
'DRY_TOTAL' => 300,
'V1_PROZ' => 4,
'V2_PROZ' => 5,
'V1_ABS' => 150,
'V2_ABS' => 180,
'V1_PROZ_WET' => 7,
'V2_PROZ_WET' => 10,
'V1_ABS_WET' => 200,
'V2_ABS_WET' => 250,
'ARRIVAL' => '2022-03-06',
),
)