簡體   English   中英

在關聯數組上使用冒泡排序時未定義的偏移量

[英]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]; 的行。

以及注意:嘗試訪問包含$y_param = $y[$key]的行的null 類型值的數組偏移量

它確實打印了一個正確排序的 asc 數組,因此代碼可以工作。

但是有沒有辦法來表達我的代碼而不收到通知?

我得到的完整輸出的屏幕截圖(有很多通知)。

您可以使用 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];
        }
    );
}

(短箭頭函數吸收周圍的范圍,因此對作者來說可以不那么冗長。)

ussort聯機幫助頁:

注意:如果兩個成員比較相等,則它們在排序數組中的相對順序未定義。

注意:此函數為數組中的元素分配新鍵。 它將刪除可能已分配的任何現有鍵,而不僅僅是重新排序鍵。

解決您未定義的索引。 您需要檢查它們是否存在。

所以而不是:

        $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 中使用多列。

如何在 PHP 中對數組和數據進行排序?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM