使用自定义排序顺序对数组进行排序,最后一个值

发布于 2024-11-30 03:23:38 字数 1776 浏览 0 评论 0原文

我正在尝试对多维数组进行排序,并且始终在数组末尾有一个值。该数组应按“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
        )

)

我做错了什么?

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.

<?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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风筝在阴天搁浅。 2024-12-07 03:23:38

您的问题在于这一行:

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 中没有找到“Last”时才执行,因为如果找到的话该函数就已经结束了。同样,最后的 return 语句(使用 strnatcmp() 调用)仅在上述两个 if 条件均未通过时执行,因为以下任一条件他们会返回一个值并结束该函数。

这是一件小事,但嵌套一堆不需要的 ifelse 块会降低代码的可读性。

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.

You should be comparing the unitText value:

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.

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.

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 (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.

It's a little thing, but nesting a bunch of unneeded if and else blocks makes the code less readable.

高冷爸爸 2024-12-07 03:23:38

最后的比较是比较 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 返回零、大于或小于零。

Your comparison at the end compares a and b which are both arrays. I get the PHP warning:

PHP [Warning] strnatcmp() expects parameter 1 to be string, array given

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文