PHP按strnatcmp和其他特定关键字排序

时间:2018-08-09 18:48:28

标签: php sorting usort

  • 我需要对一个多维数组进行排序,如下所示(已应用usort)。
  • 如果找到了标识符“ _M”(自然排序),我需要将“ 10000_M3”移至第一个键,但是不应触摸“ first”排序的顺序。
  • 额外:(可选)如果我的描述类似于“ 10000_0”,则它仍应位于索引0中
  • 如果usort可以一步完成,那就太好了
  • 我采取任何解决方案(usort,foreach,..)!!!

    usort($anArray, function ($a, $b) {
        return strnatcmp($a['description'], $b['description']);
    });
    
    $anArray = [
        // ? => [
        //     'description' => '10000_0'
        // ]
        0 => [
            'description' => '10000_D2'
        ],
        1 => [
            'description' => '10000_D3'
        ],
        2 => [
            'description' => '10000_M3'
        ],
        3 => [
            'description' => '10000_M4'
        ]
    ]
    

结果(自然存在->在第一个位置='_0'-> $ ident ='_M'在'_0'之后,如果存在):

    $result = [
        0 => [
            'description' => '10000_0'
        ]
        1 => [
            'description' => '10000_M3'
        ],
        2 => [
            'description' => '10000_M4'
        ]
        3 => [
            'description' => '10000_D2'
        ],
        4 => [
            'description' => '10000_D3'
        ],
    ]

2 个答案:

答案 0 :(得分:0)

您可以修改排序功能以分别检查特殊情况,然后再使用常规的排序方法。

R CMD SHLIB

输出:

<?php
$inputArray = [
    0 => [
        'description' => '10000_D2'
    ],
    1 => [
        'description' => '10000_D3'
    ],
    2 => [
        'description' => '10000_M3'
    ],
    3 => [
        'description' => '10000_M4'
    ],
    4 => [
         'description' => '10000_0'
    ]
];

usort($inputArray, function ($a, $b) {
    // _0 first then _M* then alphabetic

    //assume only 1 value will be _0?
    if (preg_match('/_0$/', $a['description']) === 1){
        //"a" ends in _0
        return -1;
    }
    if (preg_match('/_0$/', $b['description']) === 1){
        //"b" ends in _0
        return 1;
    }

    if (
        preg_match('/_M\d*$/', $a['description']) === 1
        && preg_match('/_M\d*$/', $b['description']) === 1
    ){
        //both have "M" so sort them normally
        return strnatcmp($a['description'], $b['description']);
    }

    if (preg_match('/_M\d*$/', $a['description']) === 1){
        //only "a" has _M
        return -1;
    }

    if (preg_match('/_M\d*$/', $b['description']) === 1){
        //only "b" has _M
        return 1;
    }

    //neither side has _M or _0 so normal sorting
    return strnatcmp($a['description'], $b['description']);
});

echo print_r($inputArray, true);
?>

我假设您只有一个_0值。如果您可以有多个_0值,则需要修改上面的代码,使其行为类似于3 _M“ if”语句。

答案 1 :(得分:0)

您可以尝试以下方法:

$anArray = [

    0 => [
        'description' => '10000_D2'
    ],
    1 => [
        'description' => '10000_D3'
    ],
    2 => [
        'description' => '10000_M3'
    ],
    3 => [
        'description' => '10000_M4'
    ]
,   4 => [
        'description' => '10000_0'
    ]
    ,   5 => [
        'description' => '10000_15'
    ]
    ,   6 => [
        'description' => '10000_789'
    ]
];
usort($anArray, function ($a, $b) {

    $tmpa=explode('_',$a['description']);
    $tmpb=explode('_',$b['description']);
        if(ctype_digit($tmpa[1])&&!ctype_digit($tmpb[1]))
            return -1;
        if(!ctype_digit($tmpa[1])&&ctype_digit($tmpb[1]))
            return 1;
        if($tmpa[1][0]==='M'&&$tmpb[1][0]!=='M')
            return -1;
        if($tmpa[1][0]!=='M'&&$tmpb[1][0]==='M')
            return 1;

        return strnatcmp($a['description'], $b['description']);
});

print_r($anArray);

,输出为:

Array
(
    [0] => Array
        (
            [description] => 10000_0
        )

    [1] => Array
        (
            [description] => 10000_15
        )

    [2] => Array
        (
            [description] => 10000_789
        )

    [3] => Array
        (
            [description] => 10000_M3
        )

    [4] => Array
        (
            [description] => 10000_M4
        )

    [5] => Array
        (
            [description] => 10000_D2
        )

    [6] => Array
        (
            [description] => 10000_D3
        )

)