PHP - 更有效的排序字母数字键的方法

时间:2014-09-15 07:22:17

标签: php arrays sorting

注意:我编辑了示例并将所有值替换为1.值无关紧要,只有键才有效。我之前写的价值导致了误解。对不起。

注意:a / b块始终是连续的。我添加这个是因为它不清楚。如果有3a / 3b和5a / 5b,则总是有4a / 4b而不仅仅是4。

我的数组包含带前导零的数字键。有时,这些编号的键有两个变体,我通过使用后缀a和b来区分。有或没有变化的键数是未知的,但是从不超过2位数;即最高数字键是'09'。

问题是这些数组键需要以数字方式排序,但是当存在后缀时,那些应该优先。单独使用kso​​rt()无法达到此目的。

例如,ksort()给了我这个:

$arr = array(
    '01' => 1,
    '02' => 1,
    '03a' => 1,
    '03b' => 1,
    '04a' => 1,
    '04b' => 1,
    '05a' => 1,
    '05b' => 1,
    '06' => 1,
);

但是,我需要这个:

$arr = array(
    '01' => 1,
    '02' => 1,
    '03a' => 1,
    '04a' => 1,
    '05a' => 1,
    '03b' => 1,
    '04b' => 1,
    '05b' => 1,
    '06' => 1,
);

我使用一些花哨的编码体操来获得我想要的东西,但它并不漂亮。我想知道是否有更好,更清洁的方式?


这就是我的工作。

1)我使用kso​​rt(),它给了我上面两个数组中的第一个。 (那个还不是我想要的那个。)

2)我创建了两个数组。一个用于'a'后缀,另一个用于'b'后缀。

$arr_a = array();
$arr_b = array();

foreach ($arr as $k => $v) {
    if (substr($k, 2) == 'a') {
        $arr_a[$k] = $v;
    } else if (substr($k, 2) == 'b') {
        $arr_b[$k] = $v;
    }
}

3)我合并了两个后缀数组。

$arr_suffixes = array_merge($arr_a, $arr_b);

4)我将原始数组切片,以便在后缀之前得到部分,在后缀之后得到部分。

$i = array_search(key($arr_suffixes), array_keys($arr));
$length = count($arr_suffixes);

$arr_before_suffixes = array_slice($arr, 0, $i);
$arr_after_suffixes = array_slice($arr, $i + $length);

5)使用array_merge,我重新组合切片数组以创建我需要的数组。

$arr = array_merge($arr_before_suffixes, $arr_suffixes);
$arr = array_merge($arr, $arr_after_suffixes);

最后,我们有正确的$ arr。有没有更好的方法来做到这一点?感觉真的很难看。

3 个答案:

答案 0 :(得分:4)

您没有正式规则。我会猜测。

$arr = array(
    '01' => 1,
    '02' => 1,
    '03a' => 1,
    '03b' => 1,
    '04a' => 1,
    '04b' => 1,
    '05a' => 1,
    '05b' => 1,
    '06' => 1,
);

uksort($arr, function($item1, $item2)
    {
    $last1 = substr($item1, -1);
    $last2 = substr($item2, -1);
    // one of the items is a number or last letters matches
    if (is_numeric($last1) || is_numeric($last2) || $last1 == $last2) 
        // simple number comparison
        return $item1 - $item2;
    else
        // natural order comparison
        return $last1 > $last2 ? 1 : -1;
    });

var_dump($arr);

答案 1 :(得分:3)

$arr = array(
    '01' => 1,
    '02' => 2,
    '03a' => 3,
    '03b' => 6,
    '04a' => 4,
    '04b' => 7,
    '05a' => 5,
    '05b' => 8,
    '06' => 9,
);

uksort(
    $arr,
    function($a, $b) {
        sscanf($a, '%d%s', $an, $as);
        sscanf($b, '%d%s', $bn, $bs);
        if ($as === null || $bs === null || $as === $bs) {
            return $an - $bn;
        }
        return strcmp($as, $bs);
    }
);
var_dump($arr);

答案 2 :(得分:2)

natsort()功能可以帮助您:

$arr = array(
    '01' => 1,
    '02' => 1,
    '03a' => 1,
    '03b' => 1,
    '04a' => 1,
    '04b' => 1,
    '05a' => 1,
    '05b' => 1,
    '06' => 1,
);
$keys = array_keys($arr);
natsort($keys);
$result = array();
foreach ($keys as $key) {
    $result[$key] = $arr[$key];
}
print_r($result); // Your expected result