在关联数组上使用冒泡排序时的未定义偏移量

问题描述

我具有此功能,可以根据键输入对关联数组进行冒泡排序,并可以选择按降序或升序进行排序:

function bubbleSort($input,$key,$order){
    while (true){
        $end = false;
        $swapped = false;
        $idx = 0;
        do {
            $x = $input[$idx];
            $y = $input[$idx + 1];
            $x_param = $x[$key];
            $y_param = $y[$key];
            if (is_null($y)) {
                $end = true;
                continue;
            }
            if ($order == "desc"){
                if ($x_param < $y_param){
                    $input[$idx] = $y;
                    $input[$idx + 1] = $x;
                    $swapped = true;
                }
            }
            else{
                if ($y_param < $x_param){
                    $input[$idx] = $y;
                    $input[$idx + 1] = $x;
                    $swapped = true;
                }
            }
            $idx++;
        }
        while ($end == false);
        if ($swapped == false) {break;}
    }
    return $input;
} 

在此示例中,我将在关联数组上使用它:

$array = array(
    array("Student Number" => 001,"Student name" => "David","Student age" => 21),array("Student Number" => 002,"Student name" => "Jonas","Student age" => 15),array("Student Number" => 003,"Student name" => "Katy","Student age" => 23));

如果我这样用print_r进行打印,它将成功排序并打印:

print_r(bubbleSort($array,"Student age","desc"));

问题是我得到注意:未定义的偏移量:3 包含 $ y = $ input [$ idx + 1];

以及注意:尝试为包含 $ y_param = $ y [$ key];

的行访问类型为null的值的数组偏移量

它确实会打印正确排序的asc数组,因此代码可以正常工作。

但是有什么方法可以使我的代码措辞得到通知吗?

Screenshot of the full output I get (with a lot of notices).

解决方法

您可以使用usort编写自己的比较函数。

<?php

$array = array(
    array("Student Number" => 001,"Student name" => "David","Student age" => 21),array("Student Number" => 002,"Student name" => "Jonas","Student age" => 15),array("Student Number" => 003,"Student name" => "Katy","Student age" => 23)
);   

function sort_array_by_key(&$array,$key,$order = 'ASC') {
    usort(
        $array,fn($a,$b) => $order == 'ASC'
            ? $a[$key] <=> $b[$key]
            : $b[$key] <=> $a[$key]
    );
}

sort_array_by_key($array,'Student name','DESC');
var_export($array);

输出:

array (
  0 => 
  array (
    'Student Number' => 3,'Student name' => 'Katy','Student age' => 23,),1 => 
  array (
    'Student Number' => 2,'Student name' => 'Jonas','Student age' => 15,2 => 
  array (
    'Student Number' => 1,'Student name' => 'David','Student age' => 21,)

删除上升/下降部分以便于阅读:

function sort_array_by_key_asc(&$array,$key) {
    usort(
        $array,function($a,$b) use ($key) {
            return $a[$key] <=> $b[$key];
        }
    );
}

(短箭头功能吸收了周围的范围,因此对作者来说可能不那么冗长。)

usort联机帮助页中:

注意:如果两个成员比较相等,则它们在 排序数组未定义。

注意:此函数将新键分配给数组中的元素。它会 删除可能已经分配的所有现有密钥,而不仅仅是 重新排序键。

,

解决未定义的索引。您需要检查它们是否存在。

所以代替:

        $x = $input[$idx];
        $y = $input[$idx + 1];
        $x_param = $x[$key];
        $y_param = $y[$key];
        if (is_null($y)) {
            $end = true;
            continue;
        }

您需要更多类似的东西:

        if(!array_key_exists($idx + 1,$input)) {
            $end = true;
            continue;
        }
        $y = $input[$idx + 1];
        $x_param = $x[$key];
        $y_param = $y[$key];

但是,请注意,您没有检查其他键的有效性。并且假设您有一个从零开始的带有顺序索引的数字索引数组。因此,您可能需要进一步检查,或使用其他方式遍历数组。


array_multisort

冒泡方法的替代方法是使用array_multisort并依靠它来完成繁重的工作。

根据您选择的键提取一列值。然后可以使用该列的排序对父数组进行排序。

底层算法是一种快速排序(我相信)。这是使用SORT_REGULAR(默认值)作为比较。您将要查找排序标志。

<?php
$array = array(
    'foo' => array("Student Number" => 001,'bar' => array("Student Number" => 002,'baz' => array("Student Number" => 003,"Student age" => 23)
);

function sort_by_key(&$array,$reverse = false) {
    $column = [];
    foreach($array as $v) {
        $column[] = $v[$key] ?? null;
    }
    $order_flag = $reverse ? SORT_DESC : SORT_ASC;
    array_multisort($column,$order_flag,$array);
}

sort_by_key($array,'Student age');
var_export($array);

输出:

array (
  'bar' => 
  array (
    'Student Number' => 2,'foo' => 
  array (
    'Student Number' => 1,'baz' => 
  array (
    'Student Number' => 3,)

您总是会发现,如果您拥有相似的值,那么您可能想要进一步对另一列进行排序,依此类推。

您可以将上面的foreach换成array_column()调用,并在array_multisort中使用多个列。

How can I sort arrays and data in PHP?

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...