2011-08-19 136 views
1

我想排序多维数组,并有一个值总是在数组的末尾。数组应该按'unitText'排序(不关心unitID如何排序),但总是将“Last”作为数组中的最后一个值。我已经差不多了,但并不是那样。使用自定义排序顺序排序数组,一个值是最后

<?php 

function cmp($a, $b) 
{ 
    /* 
    $a = preg_replace('@^(Last) @', '', $a); 
    $b = preg_replace('@^(Last) @', '', $b); 
    return strcasecmp($a, $b); 
    */ 

    if(strtolower(substr($a['unitText'],0,4))=="last") return strnatcmp($a['unitText'],9999); 
    else if(strtolower(substr($b['unitText'],0,4))=="last") return strnatcmp(9999,$b['unitText']); 
    else return strnatcmp($a, $b); 

    //return strnatcmp($a['unitText'], $b['unitText']); 

    //return end($a) > end($b); 

} 

$unit = array(
    array("unitID"=>80, "unitText"=>"Q701"), 
    array("unitID"=>30, "unitText"=>"H568"), 
    array("unitID"=>25, "unitText"=>"Last"), 
    array("unitID"=>40, "unitText"=>"Z255"), 
    array("unitID"=>20, "unitText"=>"A459") 
); 

echo "<pre>"; 
print_r($unit); 
echo "</pre>"; 

echo "<hr/>"; 

//uksort($unit['unitText'], "cmp"); 
//array_multisort($unit['unitText'], SORT_DESC, $unit['unitID'], SORT_ASC, $unit); 
usort($unit, 'cmp'); 

echo "<pre>"; 
print_r($unit); 
echo "</pre>"; 

?> 

应该结束了:

Array 
(
    [0] => Array 
     (
      [unitID] => 20 
      [unitText] => A459 
     ) 

    [1] => Array 
     (
      [unitID] => 30 
      [unitText] => H568 
     ) 

    [2] => Array 
     (
      [unitID] => 80 
      [unitText] => Q701 
     ) 

    [3] => Array 
     (
      [unitID] => 40 
      [unitText] => Z255 
     ) 

    [4] => Array 
     (
      [unitID] => 25 
      [unitText] => Last 
     ) 

) 

我在做什么错?

回答

2

你的问题是这一行:

else return strnatcmp($a, $b); 

记住$a$b都是数组,但strnatcmp()比较字符串。当这个函数被调用时,你的两个数组将被隐含地转换为字符串,它们的值都是Array,所以它们会返回相等的值并且不会被排序。

你应该比较unitText值:

else return strnatcmp($a['unitText'], $b['unitText']) 

,你没有看到这告诉我,你没有你的error_reporting层级,设定发展得足够高,事实上自认为隐式转换问题它发生时是一个E_NOTICE。在开发中,您应始终设置error_reporting(E_ALL | E_STRICT);(无论是在代码的入口点,还是在php.ini等中),以便立即标记任何小问题供您解决。

此外,如果其中一个值为'Last',您应该打电话给strnatcmp()没有理由,因为您已经知道该值应该是最后一个值。只需返回1-1(取决于哪个包含'Last')并完成它。

最后,您并不需要代码中的所有else条件。由于所有的路径发出return,你可以,如果比较失败假设任何事情后才执行的if块来了:

if (strtolower(substr($a['unitText'],0,4))=="last") { 
    return 1; 
} 

if strtolower(substr($b['unitText'],0,4))=="last") { 
    return -1; 
} 

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

在上面的,如果我们没有发现“最后第二if只执行'在$a之内,因为如果它已经结束了,函数就会结束。同样,只有在上述if条件都未通过时才会执行最后的return语句(使用strnatcmp()调用),因为它们中的任何一个都会返回值并结束该函数。

这是一件小事,但嵌套一堆不需要的ifelse块会使代码变得不可读。

+0

感谢您的建议! – kurdtpage

+0

@kurdtpage你很受欢迎。我很高兴有帮助! – AgentConundrum

0

你最后的比较比较a和b都是数组。我得到了PHP的警告:

PHP【警告】strnatcmp()预计参数1是字符串数组给定

所有的比较可以像这样被简化:

if(strtolower(substr($a['unitText'],0,4))=="last") return 1; 
else if(strtolower(substr($b['unitText'],0,4))=="last") return -1; 
else return strnatcmp($a['unitText'], $b['unitText']); 

你只需要为usort返回零,大于或小于零。