Menu

array_merge() trong PHP: gộp hai hoặc nhiều mảng

array_merge($a, $b) gộp các mảng thành một: giá trị có khóa số được nối vào cuối và đánh số lại, còn với khóa chuỗi thì mảng đứng sau thắng. Tìm hiểu array_merge khác toán tử + và cú pháp spread [...$a, ...$b] ra sao, cách gộp một danh sách các mảng, và khi nào array_merge_recursive hay array_replace phù hợp hơn.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

array_merge($a, $b) trả về một mảng mới gồm các phần tử của $a rồi đến các phần tử của $b. Khóa số được đánh số lại từ 0; khi cả hai mảng có cùng một khóa chuỗi, giá trị từ mảng đứng sau sẽ thắng. Bạn có thể truyền bao nhiêu mảng tùy thích.

array_merge() không thay đổi các đối số của nó. Hàm trả về mảng đã gộp, nên hãy gán kết quả: $all = array_merge($all, $more);.

Khóa số được đánh số lại

array_merge() coi khóa số nguyên là vị trí chứ không phải tên. Mọi phần tử có khóa số nguyên đều được nối vào cuối và nhận khóa mới bắt đầu từ 0, kể cả khi các mảng dùng cùng những con số hoặc có chỗ bị khuyết. Đó là điều bạn muốn với list, nhưng sẽ gây bất ngờ khi các con số là ID.

Khóa chuỗi trông giống số nguyên ('101') được lưu dưới dạng số nguyên, nên cũng bị đánh số lại. Khóa như 'id101' thì giữ nguyên.

array_merge vs toán tử +

Toán tử + (hợp mảng) cũng gộp các mảng, nhưng theo quy tắc ngược lại: với khóa nào đã có trong mảng bên trái, giá trị bên trái thắng và giá trị bên phải bị bỏ. Toán tử này không bao giờ đánh số lại. Vì thế + là cách tự nhiên để điền giá trị mặc định, còn array_merge() là cách tự nhiên để ghi đè chúng.

array_merge($a, $b)$a + $b
Cùng khóa chuỗigiá trị từ $bgiá trị từ $a
Khóa số nguyênđánh số lại, giữ mọi giá trịgiữ nguyên, $b thua khi trùng khóa
Cách dùng thường gặpnối list, ghi đè cài đặtđiền giá trị mặc định, giữ ID

Ví dụ cuối trong khối code là cái bẫy kinh điển của +: ['a', 'b'] + ['x', 'y', 'z'] cho ra a, b, z, vì các khóa 0 và 1 đã có ở bên trái.

Cú pháp spread: [...a,...a, ...b]

Toán tử spread mở các mảng ra bên trong một literal mảng. Nó hoạt động giống array_merge(): khóa số nguyên được đánh số lại và, từ PHP 8.1, khóa chuỗi được cho phép và khóa đứng sau thắng. Cú pháp này dễ đọc khi bạn trộn mảng với các giá trị đơn lẻ.

Để nối một mảng vào một mảng có sẵn ngay tại chỗ, xem array_push() với spread operator.

Gộp một mảng chứa các mảng

Khi các mảng cần gộp nằm sẵn trong một list, hãy spread list đó vào array_merge(). Đây cũng là cách nhanh để gộp trong vòng lặp: gom các phần lại, rồi gộp một lần.

Viết $all = array_merge($all, $batch); bên trong vòng lặp vẫn chạy được, nhưng nó sao chép toàn bộ mảng ngày càng lớn ở mỗi lần lặp, và sẽ chậm khi có hàng nghìn phần tử.

array_merge_recursive và array_replace

array_merge_recursive() gộp cả các mảng lồng nhau, nhưng với một khóa chuỗi trùng chứa giá trị thường, nó không ghi đè: nó gom cả hai giá trị vào một mảng mới. Với cấu hình, đó hiếm khi là điều bạn muốn. Trong trường hợp này array_replace_recursive() thường là công cụ đúng: nó ghi đè giá trị ở mọi cấp và giữ nguyên khóa.

Đọc ba dòng JSON từ trên xuống: array_merge() thay toàn bộ mảng db và làm mất host, array_merge_recursive() biến port và debug thành list hai phần tử, còn array_replace_recursive() cho ra đúng cấu hình bạn muốn.

Lỗi thường gặp: gộp mảng không loại bỏ gì cả

array_merge() giữ các giá trị trùng nhau nằm ở các khóa khác nhau. Gộp hai list tag sẽ khiến mỗi tag chung xuất hiện hai lần. Hãy cho kết quả đi qua array_unique() rồi array_values() để đánh số lại.

Trang array_unique trình bày cách loại bỏ phần tử trùng khỏi các hàng dữ liệu và mảng lồng nhau.

Câu hỏi thường gặp

array_merge và + trong PHP khác nhau thế nào?

Với khóa chuỗi trùng nhau, array_merge($a, $b) giữ giá trị từ $b, còn $a + $b giữ giá trị từ $a. Với khóa số, array_merge() nối mọi thứ vào cuối và đánh số lại, còn + giữ nguyên khóa số và bỏ mọi phần tử của $b có khóa đã tồn tại trong $a.

Làm sao gộp mảng mà vẫn giữ khóa số?

Dùng $a + $b nếu mảng bên trái phải thắng, hoặc array_replace($a, $b) nếu mảng bên phải phải thắng. array_merge() luôn đánh số lại khóa số bắt đầu từ 0.

Làm sao gộp một mảng chứa các mảng trong PHP?

Spread mảng bên ngoài vào array_merge(): $all = array_merge(...$lists);. Với danh sách rỗng, kết quả là []. Hãy gom các mảng trong vòng lặp trước rồi gộp một lần ở cuối; gọi array_merge() bên trong vòng lặp sẽ sao chép lại kết quả ngày càng lớn ở mỗi lần lặp.

Có dùng được spread operator với khóa chuỗi trong PHP không?

Được, từ PHP 8.1. Khi đó [...$a, ...$b] hoạt động giống array_merge($a, $b): khóa số được đánh số lại và khóa chuỗi đứng sau ghi đè khóa đứng trước.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu