在关联数组上使用冒泡排序时未定义的偏移量
Undefined offset when using bubble sort on associative array
我有这个函数可以根据键输入对关联数组进行冒泡排序,并可以选择按降序或升序排序:
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];[=35 的行=]
以及 注意:尝试访问包含 $y_param = $y[$ 的行的 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,
),
)
删除 ascending/descending 部分以便于阅读:
function sort_array_by_key_asc(&$array, $key) {
usort(
$array, function($a, $b) use ($key) {
return $a[$key] <=> $b[$key];
}
);
}
(短箭头函数吸收周围范围,因此作者可以不那么冗长。)
来自 usort 联机帮助页:
Note: If two members compare as equal, their relative order in the
sorted array is undefined.
Note: This function assigns new keys to the elements in array. It will
remove any existing keys that may have been assigned, rather than just
reordering the keys.
解决您未定义的索引。您需要检查它们是否存在。
所以代替:
$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, "Student name" => "David", "Student age" => 21),
'bar' => array("Student Number" => 002, "Student name" => "Jonas", "Student age" => 15),
'baz' => array("Student Number" => 003, "Student name" => "Katy", "Student age" => 23)
);
function sort_by_key(&$array, $key, $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,
'Student name' => 'Jonas',
'Student age' => 15,
),
'foo' =>
array (
'Student Number' => 1,
'Student name' => 'David',
'Student age' => 21,
),
'baz' =>
array (
'Student Number' => 3,
'Student name' => 'Katy',
'Student age' => 23,
),
)
您总是会发现,如果您有相似的值,您可能会想要在另一列上进一步排序,依此类推。
您可以将上面的 foreach 替换为 array_column() 调用,并在 array_multisort.
中使用多个列
How can I sort arrays and data in PHP?
我有这个函数可以根据键输入对关联数组进行冒泡排序,并可以选择按降序或升序排序:
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];[=35 的行=]
以及 注意:尝试访问包含 $y_param = $y[$ 的行的 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,
),
)
删除 ascending/descending 部分以便于阅读:
function sort_array_by_key_asc(&$array, $key) {
usort(
$array, function($a, $b) use ($key) {
return $a[$key] <=> $b[$key];
}
);
}
(短箭头函数吸收周围范围,因此作者可以不那么冗长。)
来自 usort 联机帮助页:
Note: If two members compare as equal, their relative order in the sorted array is undefined.
Note: This function assigns new keys to the elements in array. It will remove any existing keys that may have been assigned, rather than just reordering the keys.
解决您未定义的索引。您需要检查它们是否存在。
所以代替:
$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, "Student name" => "David", "Student age" => 21),
'bar' => array("Student Number" => 002, "Student name" => "Jonas", "Student age" => 15),
'baz' => array("Student Number" => 003, "Student name" => "Katy", "Student age" => 23)
);
function sort_by_key(&$array, $key, $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,
'Student name' => 'Jonas',
'Student age' => 15,
),
'foo' =>
array (
'Student Number' => 1,
'Student name' => 'David',
'Student age' => 21,
),
'baz' =>
array (
'Student Number' => 3,
'Student name' => 'Katy',
'Student age' => 23,
),
)
您总是会发现,如果您有相似的值,您可能会想要在另一列上进一步排序,依此类推。
您可以将上面的 foreach 替换为 array_column() 调用,并在 array_multisort.
中使用多个列How can I sort arrays and data in PHP?