You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何对PHP二维数组按字母数字值排序?现有代码存问题

解决方案:按数字前缀+字母后缀排序PHP数组

这个问题我之前也碰到过,你需要的是**自然排序(人类排序)**的变种——先按数字前缀排序,数字相同的再按后面的字母后缀排序。你的原代码只提取了数字部分做比较,当然会忽略字母部分;另外usort的回调函数需要返回整数(-1/0/1),不是布尔值,这也是个容易踩的小坑。

完整实现代码

针对你的二维数组,我们可以用正则拆分数字和字母部分,分两步比较:

$array = [ 
    ['id'=>1, 'name'=>1], 
    ['id'=>2, 'name'=>2], 
    ['id'=>3, 'name'=>'1b'], 
    ['id'=>4, 'name'=>'1a'], 
    ['id'=>5, 'name'=>4], 
    ['id'=>6, 'name'=>7], 
];

usort($array, function($a, $b) {
    // 用正则拆分数字前缀和字母后缀
    preg_match('/^(\d+)(.*)$/', $a['name'], $matchesA);
    preg_match('/^(\d+)(.*)$/', $b['name'], $matchesB);
    
    // 转换数字部分为整数,方便比较
    $numA = (int)$matchesA[1];
    $numB = (int)$matchesB[1];
    // 提取字母后缀(纯数字的话这里是空字符串)
    $strA = $matchesA[2];
    $strB = $matchesB[2];
    
    // 第一步:比较数字部分,升序排序
    if ($numA != $numB) {
        return $numA - $numB;
    }
    // 第二步:数字相同时,按字母后缀的字典序排序
    return strcmp($strA, $strB);
});

// 验证排序结果
print_r($array);

针对对象数组的调整(适配你的原代码)

如果你处理的是对象数组(比如原代码里的$plotsgetPlotNumber()方法),只需要把数组索引访问换成对象方法调用即可:

usort($plots, function($a, $b) {
    $nameA = $a->getPlotNumber();
    $nameB = $b->getPlotNumber();
    
    preg_match('/^(\d+)(.*)$/', $nameA, $matchesA);
    preg_match('/^(\d+)(.*)$/', $nameB, $matchesB);
    
    $numA = (int)$matchesA[1];
    $numB = (int)$matchesB[1];
    $strA = $matchesA[2];
    $strB = $matchesB[2];
    
    if ($numA != $numB) {
        return $numA - $numB;
    }
    return strcmp($strA, $strB);
});

代码工作原理

  1. 正则拆分:用/^(\d+)(.*)$/匹配每个name值,第一个捕获组提取开头的所有数字,第二个捕获组提取剩余的字符(字母或空)。
  2. 数字比较:把提取的数字转为整数,用$numA - $numB返回排序所需的整数(负数表示$a在前,正数表示$b在前)。
  3. 字母比较:数字相同时,用strcmp()比较后缀字符串,它会返回符合usort要求的整数,确保ab前面,实现字典序排序。

内容的提问来源于stack exchange,提问作者Cleggy1012

火山引擎 最新活动