Phân loại mảng kết hợp PHP

PHP cung cấp một loạt các hàm để sắp xếp dữ liệu dựa trên khóa hoặc giá trị của một mảng kết hợp. Trường hợp trở nên phức tạp là khi bạn cần sắp xếp một mảng gồm các mảng kết hợp theo một hoặc nhiều điều kiện

Đây là một nhiệm vụ rất phổ biến đối với các lập trình viên PHP vì dữ liệu được trả về từ các truy vấn cơ sở dữ liệu/SQL thường xuất hiện ở định dạng mảng kết hợp (i. e. sử dụng pg_fetch_assoc và mysql_fetch_assoc)

Hàm sắp xếp mảng cung cấp chức năng tương đương với mã được trình bày ở đây, nhưng khá phức tạp để sử dụng

Dữ liệu

Các ví dụ sau dựa trên dữ liệu sau dưới dạng một mảng kết hợp. Dữ liệu chứa sáu bản ghi, mỗi bản ghi có một giá trị cho "tên", "họ" và "tuổi"

"Mary", "lastname" => "Johnson", "age" => 25), array("firstname" => "Amanda", "lastname" => "Miller", "age" => 18), array("firstname" => "James", "lastname" => "Brown", "age" => 31), array("firstname" => "Patricia", "lastname" => "Williams", "age" => 7), array("firstname" => "Michael", "lastname" => "Davis", "age" => 43), array("firstname" => "Sarah", "lastname" => "Miller", "age" => 24), array("firstname" => "Patrick", "lastname" => "Miller", "age" => 27) ); ?>

Tập dữ liệu này có thể được biểu diễn ở định dạng bảng dưới dạng

indexfirstnamelastnameage[0]MaryJohnson25[1]AmandaMiller18[2]JamesBrown31[3]PatriciaWilliams7[4]MichaelDavis43[5]SarahMiller24[6]PatrickMiller27

Hãy bắt đầu phân loại

Sắp xếp trên một trường duy nhất

Sắp xếp các mảng kết hợp thực sự khá đơn giản - NẾU bạn biết trước trường nào bạn muốn sắp xếp theo. Ví dụ: để sắp xếp theo họ, bạn có thể sử dụng chức năng usort (tìm kiếm do người dùng xác định)

strnatcmp($a['lastname'], $b['lastname']); } // sort alphabetically by name usort($data, 'compare_lastname'); ?>

Đầu ra như sau

indexfirstnamelastnameage[0]JamesBrown31[1]MichaelDavis43[2]MaryJohnson25[3]AmandaMiller18[4]SarahMiller24[5]PatrickMiller27[6]PatriciaWilliams7

Để sắp xếp theo các trường khác nhau, chỉ cần thay thế hàm so sánh_lastname bằng một hàm sắp xếp theo tên (xem bên dưới), theo tuổi hoặc bất kỳ trường nào khác trong mảng kết hợp. Hàm strnatcmp (so sánh chuỗi "thứ tự tự nhiên") rất hữu ích ở đây vì nó có thể được áp dụng cho các số cũng như chuỗi

Dưới đây chúng ta sẽ khám phá cách sử dụng một hàm duy nhất để sắp xếp theo các trường khác nhau bằng cách chỉ định trường sắp xếp trong lệnh gọi hàm. Chức năng so sánh cũng có thể được tạo nhanh chóng dưới dạng chức năng ẩn danh

Duy trì liên kết chỉ mục

Để duy trì liên kết chỉ mục, hãy thay thế usort bằng uasort trong mã

// sort alphabetically by name uasort($data, 'compare_lastname'); ?>

với kết quả là các giá trị mảng có thể được tham chiếu bằng cách sử dụng các giá trị chỉ mục gốc

indexfirstnamelastnameage[2]JamesBrown31[4]MichaelDavis43[0]MaryJohnson25[1]AmandaMiller18[5]SarahMiller24[6]PatrickMiller27[3]PatriciaWilliams7

Điều này hữu ích khi 'chỉ mục' là id cơ sở dữ liệu cần được liên kết với từng bản ghi

Sắp xếp trên nhiều trường

Nếu bạn muốn sắp xếp theo họ VÀ tên, thì bạn có thể nghĩ rằng chỉ áp dụng hai cách sắp xếp theo thứ tự sẽ cho bạn kết quả mong muốn

// sort alphabetically by firstname, then by lastname usort($data, __NAMESPACE__ . '\compare_firstname'); usort($data, __NAMESPACE__ . '\compare_lastname'); ?>

Lưu ý rằng ở đây chúng tôi đã chỉ định không gian tên hiện tại __NAMESPACE__ để làm cho mã tương thích với các không gian tên PHP. Mặt khác, bất kỳ chức năng nào bạn vượt qua phải tồn tại trong không gian tên chung

Bạn có thể nghĩ vậy, nhưng kể từ phiên bản PHP 4. 1, usort và các hàm liên quan về cơ bản sẽ xáo trộn mảng trước khi sắp xếp (thuật toán 'không còn ổn định')

Nếu hai phần tử được so sánh bằng nhau, thì thứ tự của chúng trong mảng đã sắp xếp là không xác định

Xem bài viết Thuật toán sắp xếp nhanh của chúng tôi để biết thêm chi tiết

Điều này có nghĩa là, sau khi sắp xếp theo tên, kết quả của việc sắp xếp theo họ sẽ không nhất thiết giữ đúng thứ tự của tên

Vậy giải pháp là gì?

// sort by last name $retval = strnatcmp($a['lastname'], $b['lastname']); // if last names are identical, sort by first name if(!$retval) $retval = strnatcmp($a['firstname'], $b['firstname']); return $retval; } // sort alphabetically by firstname and lastname usort($data, __NAMESPACE__ . '\compare_fullname'); ?>

Cuối cùng, kết quả chúng tôi muốn

indexfirstnamelastnameage[0]JamesBrown31[1]MichaelDavis43[2]MaryJohnson25[3]AmandaMiller18[4]PatrickMiller27[5]SarahMiller24[6]PatriciaWilliams7

Hàm này hoạt động vì trước tiên nó so sánh họ và chỉ khi chúng giống hệt nhau thì nó mới so sánh tên để tìm ra thứ tự đúng

Bạn có thể mở rộng hàm này để sử dụng nhiều biến hơn bằng cách chèn thêm điều kiện mỗi khi $retval có giá trị bằng không

Gọi từ một lớp học

Nếu bạn đang cố gắng sắp xếp bằng cách sử dụng một hàm bên trong một lớp, thì bạn không thể chuyển hàm so sánh dưới dạng '$this->compare_fullname', mà thay vào đó cần bao gồm đối tượng hoặc tên lớp trong lệnh gọi usort. Đây là một ví dụ

.. ); public function compare_fullname($a, $b) { $retval = strnatcmp($a['lastname'], $b['lastname']); if(!$retval) return strnatcmp($a['firstname'], $b['firstname']); return $retval; } public function doStuff() { // apply sort function from INSIDE class usort($this->data, array($this, 'compare_fullname')); } } // apply sort function from OUTSIDE class $myObject = new ClassName(); usort($myObject->data, array("ClassName", 'compare_fullname')); ?>

Từ bên trong lớp $this đề cập đến cả đối tượng cũng như lớp và tất cả các chức năng liên quan. Từ bên ngoài, chúng tôi không thể sử dụng $this vì vậy phải gọi lớp theo tên

Sử dụng chức năng 'ẩn danh'

Đây là nơi nó bắt đầu trở nên thú vị. Bạn có thể tạo một chức năng ẩn danh dựa trên thông tin được thu thập trong thời gian chạy. Điều này cho phép linh hoạt hơn mà không cần mã hóa thêm

create_function('$a,$b', $code); } $compare = makeSortFunction('age'); usort($data, $compare); ?>

Cuộc gọi sau đó có thể được rút ngắn thành

Cuối cùng, bạn có thể gói tất cả vào một chức năng duy nhất như hình bên dưới. Bây giờ mã bắt đầu trông 'dễ đọc' hơn, đó là một dấu hiệu tốt

indexfirstnamelastnameage[0]PatriciaWilliams7[1]AmandaMiller18[2]SarahMiller24[3]MaryJohnson25[4]PatrickMiller27[5]JamesBrown31[6]MichaelDavis43

Bây giờ chúng ta có một hàm chung đơn giản có thể được sử dụng để sắp xếp bất kỳ mảng kết hợp nào trên một thuộc tính vô hướng duy nhất

Sử dụng 'chuyển qua tham chiếu'

Chúng ta cũng có thể truyền biến $data theo tham chiếu và không còn lo lắng về việc trả về giá trị từ hàm. Đây là cách các chức năng tích hợp như usort hoạt động (xem liên kết bên dưới để biết thêm chi tiết từ trang web PHP)

Chỉ cần thêm & vào định nghĩa hàm có nghĩa là thay vì chuyển một bản sao dữ liệu $ vào hàm, thì một tham chiếu hoặc con trỏ sẽ được chuyển. Điều đó có nghĩa là mọi thao tác của mảng trong hàm cũng sẽ được áp dụng bên ngoài hàm nên không cần lệnh trả về

Mặt khác, chức năng này tương đương với phiên bản 'chuyển theo giá trị'

Sắp xếp dựa trên danh sách các giá trị

Có những trường hợp không thể sử dụng quy trình sắp xếp dựa trên số hoặc bảng chữ cái. Giả sử rằng bạn có dữ liệu sau để trình bày trên một trang web

indexnameposition[0]Mary JohnsonThư ký[1]Amanda MillerThành viên[2]James BrownThành viên[3]Patricia WilliamsThành viên[4]Michael DavisChủ tịch[5]Sarah MillerPhó chủ tịch[6]Patrick MillerThành viên

Và bạn muốn sắp xếp các tên này theo vị trí của chúng, dựa trên danh sách sau

Một lần nữa, nó không khó như bạn nghĩ. Tất cả những gì chúng ta cần là chức năng tùy chỉnh sau

array_search($a['position'], $sortorder); $cmpb = array_search($b['position'], $sortorder); return ($cmpa > $cmpb) ? 1 : -1; } ?>

Nếu bạn không có trường thứ hai mà bạn muốn sắp xếp theo, chỉ cần thay thế dòng được đánh dấu bằng trả về 0;

Tất cả những gì chúng tôi đang làm ở đây là xem xét các giá trị trong trường vị trí. Nếu chúng giống hệt nhau thì chúng tôi sắp xếp theo trường tên để thay thế. Mặt khác, chúng tôi so sánh vị trí trong danh sách thứ tự sắp xếp, các giá trị có liên quan xuất hiện và sắp xếp dựa trên đó. Đầu ra như sau

indexnameposition[0]Michael DavisChủ tịch[1]Sarah MillerPhó chủ tịch[2]Mary JohnsonThư ký[3]Amanda MillerThành viên[4]James BrownThành viên[5]Patricia WilliamsThành viên[6]Patrick MillerThành viên

Như đã trình bày chi tiết ở trên đối với các trường hợp đơn giản hơn, giờ đây chúng tôi có thể nâng cao chức năng này để làm cho chức năng này trở nên tổng quát hơn và có thể sử dụng lại được, nhưng tôi sẽ coi đó như một bài tập cho bạn. Bạn sẽ cần chuyển mảng thứ tự sắp xếp cho hàm cùng với thông tin chi tiết về các trường cần sắp xếp theo

Nếu bạn đang làm việc trên web với loại dữ liệu này, bạn cũng có thể muốn đọc bài viết Định dạng dữ liệu dưới dạng HTML trình bày hướng dẫn chuyển đổi dữ liệu PHP sang bảng, danh sách và biểu mẫu HTML

Sắp xếp nhiều hàng bằng cách sử dụng bao đóng

Thomas Heuer từ Đức đã rất tử tế khi cung cấp mã và ví dụ sau, trông rất đẹp, nhưng sẽ chỉ hoạt động với PHP 5. 3 và cao hơn

Mảng kết hợp trong PHP là gì?

Mảng kết hợp - Nó đề cập đến một mảng có chuỗi làm chỉ mục . Thay vì lưu trữ các giá trị phần tử theo thứ tự chỉ mục tuyến tính nghiêm ngặt, điều này sẽ lưu trữ chúng kết hợp với các giá trị chính. Nhiều chỉ số được sử dụng để truy cập các giá trị trong một mảng nhiều chiều, chứa một hoặc nhiều mảng.

Làm cách nào để sắp xếp mảng kết hợp theo khóa trong PHP?

Hàm ksort() sắp xếp một mảng kết hợp theo thứ tự tăng dần, theo khóa . Mẹo. Sử dụng hàm krsort() để sắp xếp một mảng kết hợp theo thứ tự giảm dần, theo khóa. Mẹo. Sử dụng hàm asort() để sắp xếp một mảng kết hợp theo thứ tự tăng dần, theo giá trị.

Usort hoạt động như thế nào trong PHP?

Hàm usort() trong PHP sắp xếp một mảng đã cho bằng cách sử dụng hàm so sánh do người dùng định nghĩa . Hàm này rất hữu ích trong trường hợp chúng ta muốn sắp xếp mảng theo cách mới. Hàm này gán các khóa tích phân mới bắt đầu từ 0 cho các phần tử có trong mảng và các khóa cũ bị mất.

Tất cả các mảng trong PHP có liên kết không?

PHP coi tất cả các mảng là kết hợp , vì vậy không có bất kỳ hàm dựng sẵn nào.