Đây là một bài test interview PHP tôi thấy hay nên note lại.

Nói cho dễ hiểu thì mảng $exclude chứa danh sách những file/thư mục bị loại trừ. Dựa vào đó ta filter lại $files. Output sẽ là:

Nghe có vẻ dễ nhưng đề bài lại yêu cầu không dùng nested foreach() loops (foreach lồng nhau). Thật ra có cách lách luật, nó không cho xài foreach thì mình có thể xài for hoặc while là được. Do muốn gây ấn tượng nên trong bài giải không xài mấy keyword đó.

TL;DR

Để không làm mất thời gian của các bạn, đây là đáp án:

Phần dưới đây tôi sẽ giải thích cho bạn nào không hiểu đoạn code trên.

Giải thích

Tôi chia bài toán ra làm 2 phần:

  1. Loại trừ file lẻ
  2. Loại trừ file theo thư mục

Phần 1 khá dễ, chỉ cần xài array_diff là xong:

Ở phần 2, nhiệm vụ lúc này là loại trừ các file theo thư mục, ví dụ ta exclude thư mục /var/www/html thì sẽ loại các đường dẫn con của nó:

Thường thì nếu gặp trường hợp yêu cầu không được dùng nested loop thì tôi nghĩ ngay đến bộ ba array_map, array_filterarray_reduce.

Bài toán đưa ra là lọc kết quả nên ta phải dùng array_filter rồi.

Trong đoạn code trên, hàm callback trả về true thì item được giữ lại, false thì item sẽ bị loại trừ. Vấn đề là làm sao để biết item đó có nằm trong thư mục bị loại trừ hay không.

Tôi giải quyết bằng cách dùng str_replace thay lần lượt các đường dẫn exclude vào item, ở đây ta replace bằng empty hay giá trị nào cũng được. Chỉ cần biến item bị thay đổi (có chứa một trong những đường dẫn exclude) thì item đó sẽ bị loại.

Kết hợp lại ta được kết quả rút gọn như phần TL;DR.

Chú ý: Cách của tôi trông ngắn gọn nhưng chưa tối ưu performance. Bạn nào có cách hay hơn, ngắn gọn hơn hoặc tối ưu hơn xin comment ở bên dưới nhé.