按前半部分升序和后半部分降序对分隔数组值进行排序

Sort delimited array values by first half ascending then by second half descending

提问人:Gabriel91 提问时间:10/25/2023 最后编辑:mickmackusaGabriel91 更新时间:10/25/2023 访问量:38

问:

我正在尝试使用大小对数组值进行排序,但结果与我预期不符。 这是我的代码:

function cmp($a, $b) {
    $sizes = array(
        "XS" => 0,  
        "S" => 1,
        "M" => 2,
        "L" => 3,
    );

    $size_a = explode("_", $a)[1];
    $size_b = explode("_", $b)[1];

    return $sizes[$size_a] <=> $sizes[$size_b];
}
    
$array = array("GL001_M","GL001_XS","GL001_S",                  
                "GL001_L","GL002_M","GL002_XS",
                "GL002_S","GL002_L");

usort($array,"cmp");

foreach($array as $arrayItem){
    echo $arrayItem.' | ';
}

我的输出是这样的:

GL001_XS | GL002_XS | GL001_S | GL002_S | GL001_M | GL002_M | GL001_L | GL002_L | 

相反,我想要这个:

GL001_XS | GL001_S | GL001_M | GL001_L | GL002_XS | GL002_S | GL002_M | GL002_L | 
PHP 数组排序 usort 自定义排序

评论

1赞 Barmar 10/25/2023
你能解释一下你想要的分类是什么吗?您的函数按大小排序,这就是您得到的结果。

答:

3赞 Nigel Ren 10/25/2023 #1

当前方法的问题在于它只对每个字符串的最后部分(如“S”、“XS”等)进行排序。

您可以做的是扩展比较以对第一部分(“GL001”)进行排序,并且仅在存在匹配项时才使用大小对它们进行排序。

$size_a = explode('_', $a);
$size_b = explode('_', $b);

return ($size_a[0] <=> $size_b[0]) ?: $sizes[$size_a[1]] <=> $sizes[$size_b[1]];

因此将比较“GL001”位。$size_a[0] <=> $size_b[0]

如果第一部分的值为 0(即它们相同),则使用它将返回第二部分。
将是数组转换的大小(所以 'S' => 1)。
?:$sizes[$size_a[1]]

0赞 mickmackusa 10/25/2023 #2

哇,这个问题与表示大小(XXS、XS、S、M、L、XL、XXL)的值后缀的自定义排序非常相似,但事实上,您按输入字符串的两半进行排序,并且所需的大小值可以按字母顺序排序,我的建议会改变。不需要查找数组。使用线性时间复杂度的调用意味着每次迭代的调用次数少于 2 次。explode()explode()usort()

代码:(演示)

$ids = [];
$sizes = [];
foreach ($array as $v) {
    [$ids[], $sizes[]] = explode('_', $v, 2);
}
array_multisort($ids, $sizes, SORT_DESC, $array);
var_export($array);

一旦必须容纳大于 的大小,就需要一个查找数组。L

代码:(演示)

define('SIZES', array_flip(['XXS', 'XS', 'S', 'M', 'L', 'XL', 'XXL']));

$ids = [];
$sizes = [];
foreach ($array as $v) {
    [$ids[], $size] = explode('_', $v, 2);
    $sizes[] = SIZES[$size];
}
array_multisort($ids, $sizes, $array);
var_export($array);

如果你对与你合作的其他开发人员非常不满,你就会用这个功能齐全的风格片段让他们眼花缭乱,没有新的、全局范围的变量!演示

define('SIZES', array_flip(['XXS', 'XS', 'S', 'M', 'L', 'XL', 'XXL']));

array_multisort(
    ...array_merge(
        array_map(
            null,
            ...array_map(
                fn($v) =>
                    (fn($id, $size) => [$id, SIZES[$size]])(...explode('_', $v, 2)),
                    $array
            )
        ),
        [&$array]
    )
);
var_export($array);