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

问题描述 投票:0回答:2

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

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 arrays sorting usort custom-sort
2个回答
3
投票

当前方法的问题是它仅对每个字符串的最后部分进行排序(因此“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]];

因此

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

使用

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


0
投票

哇,这个问题与对代表尺寸的值后缀进行自定义排序(XXS,XS,S,M,L,XL,XXL)非常相似,但事实上您是按输入字符串的两半和所需的尺寸值可以按字母顺序排序,我的建议会改变。不需要查找数组。以线性时间复杂度调用

explode()
意味着每次
explode()
迭代的
usort()
调用次数少于 2 次。

代码:(演示

foreach ($array as $v) {
    [$ids[], $sizes[]] = explode('_', $v, 2);
}
array_multisort($ids, $sizes, SORT_DESC, $array);
var_export($array);
© www.soinside.com 2019 - 2024. All rights reserved.