I am trying to sort a multi dimensional array, and have one value always at the end of the array. The array should be sorted by 'unitText' (dont care how unitID is sorted), but always have "Last" as the last value in the array. I've almost got it, but not quite there.
我正在尝试对多维数组进行排序,并且总是在数组的末尾有一个值。数组应按'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>";
?>
Should end up with:
最终应该:
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
)
)
What am I doing wrong?
我究竟做错了什么?
2 个解决方案
#1
3
Your problem is with this line:
你的问题在于这一行:
else return strnatcmp($a, $b);
Remember that $a
and $b
are both arrays, but strnatcmp()
compares strings. When this function is called, your two arrays will be implicitly cast to strings, which will both have the value of Array
, so they will return as equal and will not be sorted.
请记住$ a和$ b都是数组,但strnatcmp()比较字符串。调用此函数时,您的两个数组将被隐式转换为字符串,这两个字符串都具有Array的值,因此它们将返回相等且不会被排序。
You should be comparing the unitText
value:
你应该比较unitText值:
else return strnatcmp($a['unitText'], $b['unitText'])
The fact that you didn't see this tells me that you don't have your error_reporting
level set high enough in development, since that implicit cast issues an E_NOTICE
when it occurs. In development, you should always have error_reporting(E_ALL | E_STRICT);
set (either at the entry point for your code, or in your php.ini
, etc.) so that any little issues get immediately flagged for you to fix.
您没有看到这一点的事实告诉我您没有在开发中将error_reporting级别设置得足够高,因为隐式转换会在发生时发出E_NOTICE。在开发中,你应该总是有error_reporting(E_ALL | E_STRICT);设置(在您的代码的入口点,或在您的php.ini等),以便立即标记任何小问题,以便您修复。
Also, there is no reason why you should be calling strnatcmp()
at all when one of the values is 'Last', because you already know that the value should be last. Just return 1
or -1
(depending on which contains 'Last') and be done with it.
此外,当其中一个值为“Last”时,您根本没有理由调用strnatcmp(),因为您已经知道该值应该是最后一个。只需返回1或-1(取决于哪个包含'Last')并完成它。
Finally, you don't need all the else
conditions in the code. Since all paths issue a return
, you can assume that anything that comes after an if
block is only executed if the comparison fails:
最后,您不需要代码中的所有其他条件。由于所有路径都发出返回,因此您可以假设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']);
In the above, the second if
only executes if we didn't find 'Last' within $a
, since the function would have already ended if it had. Similarly, the final return
statement (with the strnatcmp()
call) only executes if neither of the above if
conditions passed, because either one of them would have returned a value and ended the function.
在上面,如果我们没有在$ a中找到'Last',则第二个if执行,因为如果函数已经结束,它将已经结束。类似地,最终的return语句(使用strnatcmp()调用)仅在上述if条件都没有通过的情况下才执行,因为其中任何一个都返回了一个值并结束了该函数。
It's a little thing, but nesting a bunch of unneeded if
and else
blocks makes the code less readable.
这是一个小东西,但嵌套一堆不需要的if和else块会使代码的可读性降低。
#2
0
Your comparison at the end compares a and b which are both arrays. I get the PHP warning:
最后的比较比较了a和b,它们都是数组。我收到了PHP警告:
PHP [Warning] strnatcmp() expects parameter 1 to be string, array given
PHP [警告] strnatcmp()期望参数1为字符串,给定数组
All of the comparisons could be simplified like so:
所有的比较都可以这样简化:
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']);
You only need to return zero, greater than or less than zero for the usort.
您只需要为usort返回零,大于或小于零。
#1
3
Your problem is with this line:
你的问题在于这一行:
else return strnatcmp($a, $b);
Remember that $a
and $b
are both arrays, but strnatcmp()
compares strings. When this function is called, your two arrays will be implicitly cast to strings, which will both have the value of Array
, so they will return as equal and will not be sorted.
请记住$ a和$ b都是数组,但strnatcmp()比较字符串。调用此函数时,您的两个数组将被隐式转换为字符串,这两个字符串都具有Array的值,因此它们将返回相等且不会被排序。
You should be comparing the unitText
value:
你应该比较unitText值:
else return strnatcmp($a['unitText'], $b['unitText'])
The fact that you didn't see this tells me that you don't have your error_reporting
level set high enough in development, since that implicit cast issues an E_NOTICE
when it occurs. In development, you should always have error_reporting(E_ALL | E_STRICT);
set (either at the entry point for your code, or in your php.ini
, etc.) so that any little issues get immediately flagged for you to fix.
您没有看到这一点的事实告诉我您没有在开发中将error_reporting级别设置得足够高,因为隐式转换会在发生时发出E_NOTICE。在开发中,你应该总是有error_reporting(E_ALL | E_STRICT);设置(在您的代码的入口点,或在您的php.ini等),以便立即标记任何小问题,以便您修复。
Also, there is no reason why you should be calling strnatcmp()
at all when one of the values is 'Last', because you already know that the value should be last. Just return 1
or -1
(depending on which contains 'Last') and be done with it.
此外,当其中一个值为“Last”时,您根本没有理由调用strnatcmp(),因为您已经知道该值应该是最后一个。只需返回1或-1(取决于哪个包含'Last')并完成它。
Finally, you don't need all the else
conditions in the code. Since all paths issue a return
, you can assume that anything that comes after an if
block is only executed if the comparison fails:
最后,您不需要代码中的所有其他条件。由于所有路径都发出返回,因此您可以假设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']);
In the above, the second if
only executes if we didn't find 'Last' within $a
, since the function would have already ended if it had. Similarly, the final return
statement (with the strnatcmp()
call) only executes if neither of the above if
conditions passed, because either one of them would have returned a value and ended the function.
在上面,如果我们没有在$ a中找到'Last',则第二个if执行,因为如果函数已经结束,它将已经结束。类似地,最终的return语句(使用strnatcmp()调用)仅在上述if条件都没有通过的情况下才执行,因为其中任何一个都返回了一个值并结束了该函数。
It's a little thing, but nesting a bunch of unneeded if
and else
blocks makes the code less readable.
这是一个小东西,但嵌套一堆不需要的if和else块会使代码的可读性降低。
#2
0
Your comparison at the end compares a and b which are both arrays. I get the PHP warning:
最后的比较比较了a和b,它们都是数组。我收到了PHP警告:
PHP [Warning] strnatcmp() expects parameter 1 to be string, array given
PHP [警告] strnatcmp()期望参数1为字符串,给定数组
All of the comparisons could be simplified like so:
所有的比较都可以这样简化:
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']);
You only need to return zero, greater than or less than zero for the usort.
您只需要为usort返回零,大于或小于零。