Menu

Hàm in_array() trong PHP: kiểm tra giá trị có trong mảng

in_array($needle, $haystack) trả về true khi giá trị có trong mảng. Truyền true làm đối số thứ ba để kiểm tra nghiêm ngặt, in_array('1', $ids, true), khi đó kiểu dữ liệu cũng phải khớp. Tìm hiểu cờ strict, tìm kiếm không phân biệt hoa thường, kiểm tra nhiều giá trị, mảng lồng nhau và cách tra cứu nhanh bằng isset.

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.

in_array($needle, $haystack) trả về true nếu giá trị nằm đâu đó trong mảng và false nếu không. Truyền true làm đối số thứ ba, in_array($needle, $haystack, true), để yêu cầu cả kiểu dữ liệu cũng phải giống; đây là dạng nghiêm ngặt nên dùng mặc định.

in_array() chỉ xét các giá trị. Để kiểm tra một khóa có tồn tại hay không, hãy dùng array_key_exists() hoặc isset().

Tham số strict

Không có đối số thứ ba, in_array() so sánh bằng ==, tức là chuyển đổi kiểu trước khi so sánh. Với true, hàm so sánh bằng ===: cả giá trị lẫn kiểu dữ liệu đều phải khớp. Khác biệt lộ ra ngay khi mảng trộn lẫn số và chuỗi, điều rất hay gặp với dữ liệu từ form, URL và tệp CSV.

Mỗi ô bên dưới là kết quả == và === trả về cho cặp giá trị đó trong PHP 8.3. in_array() trả lời true nếu needle và một phần tử bất kỳ cho ra true trong bảng, ứng với chế độ bạn dùng. Chuyển qua lại giữa các tab và để ý các hàng null, true và chuỗi số.

in_array loose (==) vs strict (===) matches
Point at or tap a cell to read it as PHP.
$a == $btruefalsenull01"0""1""""abc""10""1e1"10[]
true
false
null
0
1
"0"
"1"
""
"abc"
"10"
"1e1"
10
[]
Every cell computed by PHP 8.3.19.

Có một quy tắc đã thay đổi trong PHP 8: chuỗi không phải số không còn bằng 0 nữa, nên in_array('abc', [0]) hiện nay là false nhưng từng là true trong PHP 7. Code viết cho PHP 7 đôi khi dựa vào điều đó, thêm một lý do nữa để truyền true và không phụ thuộc vào các quy tắc chuyển đổi. Trang toán tử so sánh giải thích đầy đủ các quy tắc này.

in_array không phân biệt hoa thường

in_array() so sánh chuỗi chính xác từng ký tự, nên 'PHP' và 'php' là khác nhau. Hãy chuyển cả needle lẫn mảng về chữ thường trước khi kiểm tra. mb_strtolower() xử lý được cả chữ có dấu và chữ không thuộc bảng Latin.

Kiểm tra nhiều giá trị cùng lúc

in_array() chỉ nhận một needle. Với nhiều giá trị, hãy so sánh các mảng như tập hợp: array_diff() trả về những needle bị thiếu, nên kết quả rỗng nghĩa là có đủ tất cả, còn array_intersect() trả về những needle tìm thấy.

array_diff() và array_intersect() so sánh giá trị dưới dạng chuỗi, nên ở đây 1 và '1' được coi là bằng nhau.

in_array trên mảng đa chiều

in_array() không tìm bên trong các mảng lồng nhau. Để kiểm tra xem có hàng nào chứa một trường với giá trị cho trước, hãy lấy trường đó ra trước bằng array_column(), rồi tìm trong danh sách phẳng.

Dòng cuối cho thấy needle cũng có thể là một mảng: nó khớp với hàng giống hệt, cùng khóa, cùng giá trị và cùng thứ tự.

in_array, array_search và isset

Cả ba đều trả lời câu hỏi "có hay không?", nhưng trả về kết quả khác nhau và chạy với tốc độ khác nhau:

Lệnh gọiTrả vềTốc độ trên mảng lớn
in_array($v, $arr, true)true hoặc falseduyệt mọi phần tử
array_search($v, $arr, true)khóa, hoặc falseduyệt mọi phần tử
isset($set[$v])true hoặc falsemột lần tra cứu bảng băm

Dùng array_search() khi bạn cần biết giá trị nằm ở đâu. Khi kiểm tra nhiều giá trị với cùng một danh sách lớn, hãy lật danh sách một lần để giá trị trở thành khóa, rồi dùng isset().

Thời gian thay đổi sau mỗi lần chạy, nhưng khoảng cách thì không: tra cứu bằng isset() giữ nguyên tốc độ, còn in_array() chậm dần theo kích thước danh sách. array_flip() chỉ dùng được với giá trị là chuỗi và số nguyên, và các giá trị trùng nhau gộp thành một khóa, điều này không ảnh hưởng gì khi chỉ kiểm tra có hay không.

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

Tham số thứ ba của in_array dùng để làm gì?

Nó bật chế độ so sánh nghiêm ngặt. in_array($x, $arr, true) so sánh bằng ===, nên ngoài giá trị thì kiểu dữ liệu cũng phải khớp: in_array('1', [1, 2], true) là false. Không có tham số này, PHP so sánh bằng == và chuyển đổi kiểu trước.

Có nên luôn dùng chế độ strict với in_array không?

Thường là có. Chế độ lỏng khiến in_array(null, [0]), in_array(true, ['any string']) và in_array('1e1', ['10']) đều trả về true. Chỉ tắt nó khi bạn cố ý muốn '5' từ form khớp với số nguyên 5.

Làm sao để in_array không phân biệt chữ hoa chữ thường?

Chuyển cả hai vế về chữ thường: in_array(strtolower($needle), array_map('strtolower', $haystack), true). Dùng mb_strtolower khi văn bản có thể chứa chữ cái ngoài bảng ASCII.

Làm sao kiểm tra nhiều giá trị có trong mảng hay không?

Để yêu cầu có tất cả, kiểm tra rằng không còn gì sót lại: !array_diff($needles, $haystack). Để yêu cầu có ít nhất một, kiểm tra phần giao nhau: (bool) array_intersect($needles, $haystack).

in_array có chậm không?

Hàm này duyệt mảng từng phần tử một, nên sẽ chậm với mảng lớn được kiểm tra nhiều lần. Hãy lật mảng một lần với $set = array_flip($haystack); rồi dùng isset($set[$value]), chỉ tốn một lần tra cứu bảng băm.

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