PHP 排序数组的非关联数组,但开头有字符串值

PHP sorting array of non-associative arrays but having string values at the beginning

提问人:m.yagmur 提问时间:7/7/2022 最后编辑:m.yagmur 更新时间:7/13/2022 访问量:196

问:

 $unresponsives =   [
    [
        "Customer",
        "172.52.46.75",
        "2022-04-01 16:20:45",
        "1817",
        "nxlog",
        "2327.02 Hours"
    ],
    [
        "Customer",
        "172.25.89.45",
        "2022-04-01 16:20:45",
        "1817",
        "nxlog",
        "2327.02 Hours"
    ],
    [
        "Customer",
        "172.19.10.94",
        "2022-04-01 16:20:45",
        "1817",
        "nxlog",
        "2327.02 Hours"
    ]]

这是我的数组数组中的一个示例。我想按第五个元素(小时)降序对数组进行排序。我能够使用 usort 实现这一点,但在数组中也有以字符串“Undefined”作为第五个值的数组。示例如下:

[
        "PreProd",
        "178.18.15.12",
        "\/",
        "1502",
        "iis",
        "Undefined"
    ]

目前,它们在排序完成后列在数组的底部。相反,我希望它们列在数组的开头。因此,首先是具有未定义数组的数组,然后是其余数组的降序。我怎样才能做到这一点?

以下是我使用的 usort 函数:

usort($unresponsives, function ($unresponsive1, $unresponsive2) {
            return floatval($unresponsive2[5]) <=> floatval($unresponsive1[5]);
        });
PHP 数组 排序 usort

评论

0赞 Vinay Patil 7/7/2022
添加有问题的预期输出
1赞 RiggsFolly 7/7/2022
为示例提供至少一行也很有用undefined
0赞 outis 7/8/2022
注意“第 5 个元素”对应于索引 4,因为前者是序数,后者是偏移量。

答:

-2赞 Faiz Sandhi 7/7/2022 #1

请看下面的片段

echo '<pre>';
function ShortFunction($new,$old){
    return floatval($old[5]) <=> floatval($new[5]);
}
$new_array = usort($unresponsives,'ShortFunction');
print_r($unresponsives);

评论

0赞 mickmackusa 7/9/2022
“试试这个”的答案在 Stack Overflow 上的价值很低,因为它们错过了教育/授权提问者和数千名未来研究人员的机会。
0赞 Will B. 7/8/2022 #2

array_multisort方法 - 示例 https://3v4l.org/SuJQX

对于稍微复杂的方法,允许根据需要对排序进行细粒度控制。用于检索小时数。在小时上用于确定筛选的值位置,并循环访问这些位置以将其指定为数值。然后可以与所需的标志一起使用,对生成的数组进行排序。array_columnarray_keysarray_multisort

$hours = array_column($unresponsives, 5);
if ($undefined = array_keys($hours, 'Undefined')) { 
    $hours = array_replace($hours, array_fill_keys($undefined, PHP_INT_MAX));
}
array_multisort($hours, SORT_DESC, SORT_NUMERIC, $unresponsives);

结果

var_export($unresponsives);

array (
  0 => 
  array (
    0 => 'Customer',
    1 => '172.19.10.94',
    2 => '2022-04-01 16:20:45',
    3 => '1817',
    4 => 'nxlog',
    5 => 'Undefined',
  ),
  1 => 
  array (
    0 => 'Customer',
    1 => '172.25.89.45',
    2 => '2022-04-01 16:20:45',
    3 => '1817',
    4 => 'nxlog',
    5 => 'Undefined',
  ),
  2 => 
  array (
    0 => 'Customer',
    1 => '172.52.46.75',
    2 => '2022-04-01 16:20:45',
    3 => '1817',
    4 => 'nxlog',
    5 => '2328.02 Hours',
  ),
  3 => 
  array (
    0 => 'Customer',
    1 => '172.19.10.94',
    2 => '2022-04-01 16:20:45',
    3 => '1817',
    4 => 'nxlog',
    5 => '2324.02 Hours',
  ),
  4 => 
  array (
    0 => 'Customer',
    1 => '172.19.10.94',
    2 => '2022-04-01 16:20:45',
    3 => '1817',
    4 => 'nxlog',
    5 => '2322.02 Hours',
  ),
)

升序数字排序

更改要换出的排序顺序,具体取决于您希望筛选后的值驻留在数组中的哪个位置。SORT_ASCPHP_INT_MAXPHP_INT_MIN

$hours = array_column($unresponsives, 5);
if ($undefined = array_keys($hours, 'Undefined')) {    
    $hours = array_replace($hours, array_fill_keys($undefined, PHP_INT_MIN));
}
array_multisort($hours, SORT_ASC, SORT_NUMERIC, $unresponsives);

结果

var_export($unresponsives);

array (
  0 => 
  array (
    0 => 'Customer',
    1 => '172.19.10.94',
    2 => '2022-04-01 16:20:45',
    3 => '1817',
    4 => 'nxlog',
    5 => 'Undefined',
  ),
  1 => 
  array (
    0 => 'Customer',
    1 => '172.25.89.45',
    2 => '2022-04-01 16:20:45',
    3 => '1817',
    4 => 'nxlog',
    5 => 'Undefined',
  ),
  2 => 
  array (
    0 => 'Customer',
    1 => '172.19.10.94',
    2 => '2022-04-01 16:20:45',
    3 => '1817',
    4 => 'nxlog',
    5 => '2322.02 Hours',
  ),
  3 => 
  array (
    0 => 'Customer',
    1 => '172.19.10.94',
    2 => '2022-04-01 16:20:45',
    3 => '1817',
    4 => 'nxlog',
    5 => '2324.02 Hours',
  ),
  4 => 
  array (
    0 => 'Customer',
    1 => '172.52.46.75',
    2 => '2022-04-01 16:20:45',
    3 => '1817',
    4 => 'nxlog',
    5 => '2328.02 Hours',
  ),
)

usort方法 - 示例 https://3v4l.org/Uoml6

通过在条件中操作所需过滤值的比较值,可以应用将过滤值指定为数值的相同方法,该条件仅用于对数组进行排序。usort

降序

function compd($a, $b)
{
    /*
    # Condensed Syntax
    return ('Undefined' === $b[5] ? PHP_INT_MAX : floatval($b[5])) <=> ('Undefined' === $a[5] ? PHP_INT_MAX : floatval($a[5]));
    */

     $v1 = $a[5];
     $v2 = $b[5];
     if ('Undefined' === $v1) {
         $v1 = PHP_INT_MAX;
     }
     if ('Undefined' === $v2) {
         $v2 = PHP_INT_MAX;
     }

     return floatval($v2) <=> floatval($v1);
}

usort($unresponsives, 'compd');

升序

与该方法一样,通过交换来更改排序顺序,但也要交换比较以按升序对值进行排序。array_multisortPHP_INT_MAXPHP_INT_MIN$b[5] <=> $a[5]$a[5] <=> $b[5]

function compa($a, $b) 
{
    /*
    # Condensed Syntax
    return ('Undefined' === $a[5] ? PHP_INT_MIN : floatval($a[5])) <=> ('Undefined' === $b[5] ? PHP_INT_MIN : floatval($b[5]));
    */

     $v1 = $a[5];
     $v2 = $b[5];
     if ('Undefined' === $v1) {
         $v1 = PHP_INT_MIN;
     }
     if ('Undefined' === $v2) {
         $v2 = PHP_INT_MIN;
     }

     return floatval($v1) <=> floatval($v2);
}

usort($unresponsives, 'compa');
0赞 mickmackusa 7/9/2022 #3

我建议两个步骤。

  1. 使用可比较的数值填充数组。
  2. 调用以在 DESC 方向上进行比较。array_multisort()

代码:(演示)

array_multisort(
    array_map(
        fn($a) => sscanf($a[5], '%f')[0] ?? PHP_INT_MIN,
        $unresponsives
    ),
    SORT_DESC,
    $unresponsives
);
var_export($unresponsives);

这也可以在完全没有迭代函数调用的情况下执行,以提高效率。

第一条规则在评估之前检查值和顺序评估。第二条规则仅在需要决胜局时应用,在这种情况下,将比较 DESC 排序方向的浮点值。Undefinedtruefalse

代码:(演示)

usort(
    $unresponsives,
    fn($a, $b) => 
        [$b[5] === 'Undefined', (float) $b[5]]
        <=>
        [$a[5] === 'Undefined', (float) $a[5]]
);
var_export($unresponsives);

类似的方法可以在这里找到。

评论

0赞 RiggsFolly 7/13/2022
不是我的反对票,意识到你是对的,我的代码只适用于问题中提供的数据。
0赞 RiggsFolly 7/13/2022
呜,你是对的,当我打算用你的答案时,我得到了另一个答案。我真的需要一个好的长假