Xử lý dữ liệu kiểu mảng (array) trong PHP

    0

    Trong bài học trước bạn đã biết khái niệm về kiểu dữ liệu mảng, cách khai báo mảng, và cách truy xuất phần tử của mảng. Trong PHP, mảng là một kiểu dữ liệu tập hợp mạnh mẽ, đa năng. Mảng không chỉ được sử dụng cho lưu trữ dữ liệu mà còn là nền tảng cho nhiều kiểu dữ liệu tập hợp khác (như tập toán học set, ngăn xếp stack, hàng đợi queue, v.v.).

    Có thể nói, nắm được cách làm việc với mảng là một trong những yêu cầu quan trọng nhất trong giai đoạn học lập trình PHP cơ bản.

    Để phát huy các khả năng của dữ liệu mảng, bạn cần biết nhiều thao tác cơ bản với loại dữ liệu này, như thêm/bớt phần tử, duyệt mảng, lọc dữ liệu mảng, sắp xếp mảng, tìm kiếm trong mảng, thực hiện các phép toán tổng hợp trên mảng, v.v..

    Thêm phần tử mới vào mảng

    PHP cung cấp một số cách để thêm phần tử mới vào mảng. Lưu ý rằng các phương pháp này đều thêm phần tử vào cuối mảng.

    Đối với mảng chỉ số có thể dùng phương pháp sau:

    $emails = array();
    $emails[] = 'trump.donald@gmail.com';
    $emails[] = 'obama.barack@gmail.com';
    $emails[] = 'bush.george@gmail.com';
    
    // dùng lệnh này để xem thông tin chi tiết về biến
    var_dump($emails);

    Kết quả chạy lệnh var_dump($emails) như sau:

    array(3) {
    [0] =>
    string(22) "trump.donald@gmail.com"
    [1] =>
    string(22) "obama.barack@gmail.com"
    [2] =>
    string(21) "bush.george@gmail.com"
    }

    Ở đây chúng ta sử dụng phép toán truy xuất phần tử của mảng nhưng không cung cấp chỉ số.

    Khi dùng phương pháp này PHP tự động tính chỉ số cho mỗi phần tử thêm vào cuối mảng. Quy tắc tính giá trị cho chỉ số tiếp theo là lấy chỉ số lớn nhất hiện có cộng thêm 1.

    Lưu ý rằng, bạn cũng có thể tự đặt chỉ số trong cặp ngoặc vuông []. Nếu đặt chỉ số chưa tồn tại, giá trị đó sẽ được thêm vào mảng. Nếu sử dụng chỉ số đã tồn tại, giá trị mới sẽ đè lên giá trị cũ. Các chỉ số cũng không cần liên tục. Ví dụ, bạn hoàn toàn có thể thêm giá trị như sau:

    $emails = [];
    $emails[] = 'trump.donald@gmail.com'; // tự động tính, 0
    $emails[11] = 'obama.barack@gmail.com'; // tự gán, 11
    $emails[2] = 'bush.george@gmail.com'; // tự gán, 2 (nhưng đi sau 11)
    $emails[] = 'clinton.bill@gmail.com'; // tự động tính, 11 (chỉ số lớn nhất hiện có) + 1
    
    var_dump($emails);
    array(4) {
    [0] =>
    string(22) "trump.donald@gmail.com"
    [11] =>
    string(22) "obama.barack@gmail.com"
    [2] =>
    string(21) "bush.george@gmail.com"
    [12] =>
    string(22) "clinton.bill@gmail.com"
    }

    Nói tóm lại, đối với mảng chỉ số, bạn có thể sử dụng phép toán truy xuất phần tử với chỉ số chưa tồn tại hoặc chỉ số tính tự động để thêm phần tử.

    Đối với mảng kết hợp, phương pháp thực hiện tương tự như truy xuất phần tử nhưng sử dụng khóa chưa tồn tại:

    $book = []; // tạo một mảng rỗng rồi lần lượt thêm từng cặp khóa/giá trị
    $book['title'] = 'PHP programming for dummy'; // khóa 'title', giá trị 'PHP programming for dummy'
    $book['authors'] = 'Trump D.';
    $book['publisher'] = 'Washington';
    var_dump($book);
    array(3) {
    'title' =>
    string(25) "PHP programming for dummy"
    'authors' =>
    string(8) "Trump D."
    'publisher' =>
    string(10) "Washington"
    }

    Nếu bạn sử dụng một khóa đã có sẵn, PHP sẽ hiểu đó là phép toán truy xuất và sẽ ghi đè giá trị cũ. Nếu bạn sử dụng một khóa mới, PHP sẽ thêm phần tử này vào mảng.

    Một phương pháp nữa là sử dụng hàm array_push():

    $capital_cities = ['Hanoi', 'Washington'];
    array_push($capital_cities, 'Moscow', 'Beijing', 'Tokyo');
    var_dump($capital_cities);
    array(5) {
    [0] =>
    string(5) "Hanoi"
    [1] =>
    string(10) "Washington"
    [2] =>
    string(6) "Moscow"
    [3] =>
    string(7) "Beijing"
    [4] =>
    string(5) "Tokyo"
    }

    Phương pháp này chỉ sử dụng được cho mảng chỉ số. Bạn không thể cung cấp cặp khóa => giá_trị cho hàm array_push().

    array_push() cùng với array_pop() cho phép sử dụng mảng như một stack.

    Duyệt mảng trong PHP, lệnh lặp foreach

    Để duyệt mảng nói chung phải sử dụng lệnh lặp.

    Tuy nhiên, do đặc thù của mảng trong PHP, việc sử dụng các lệnh lặp thông thường while, do-while, for không phù hợp.

    Như bạn đã biết, mảng trong PHP có thể sử dụng chỉ số (số nguyên) hoặc khóa (chuỗi ký tự). Chỉ số có và khóa thể gán tùy ý chứ không nhất thiết phải theo quy luật nào.

    Khi đó, việc duyệt mảng với các lệnh lặp thông thường có thể bỏ sót phần tử hoặc không thực hiện được.

    Để duyệt mảng, PHP cung cấp một lệnh lặp riêng: foreach. Hãy xem ví dụ sau:

    $days = [2 => 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
    foreach ($days as $day) {
        echo $day ."\t";
    }
    Monday Tuesday Wednesday Thursday Friday Saturday Sunday

    Cú pháp sử dụng lệnh lặp foreach như sau: foreach($mảng as $biến_tạm) { ... }

    Lệnh lặp foreach sử dụng mẫu thiết kế iterator và chỉ số nội bộ của mảng để lần lượt duyệt qua từng phần tử. Khi dừng lại ở phần tử nào, giá trị của nó được copy sang biến tạm (as $biến_tạm). Bạn sử dụng giá trị của phần tử thông qua biến tạm này. Do biến tạm chỉ là bản copy, những thay đổi trên biến này không ảnh hưởng đến phần tử tương ứng của mảng.

    Cú pháp trên chỉ lấy phần giá trị đưa vào biến tạm mà bỏ qua phần khóa/chỉ số. Trong trường hợp bạn cần lấy cả chỉ số (mảng chỉ số) hoặc khóa (mảng kết hợp), bạn cần dùng cú pháp hơi khác: foreach($mảng as $khóa => $giá_trị) { ... } .

    Hãy xem ví dụ sau:

    $trump = [
        'first name' => 'Donald',
        'last name' => 'Trump',
        'age' => 74,
    ];
    
    foreach ($trump as $key => $info) {
        echo "$key: $info\r\n";
    }
    first name: Donald
    last name: Trump
    age: 74

    Ở đây, khi dừng lại ở phần tử nào của mảng, lệnh lặp foreach sẽ copy khóa của nó sang biến $key, và copy giá trị của nó sang biến $info.

    Với cách này, khi dừng ở phần tử nào, lệnh lặp foreach copy khóa và giá trị của phần tử tương ứng sang cặp biến tạm để bạn sử dụng.

    Đối với mảng của mảng, bạn cần sử dụng kết hợp các lệnh lặp foreach lồng nhau.

    Một cách khác để duyệt mảng là sử dụng kết hợp hàm list() và each(). Hãy xem ví dụ sau:

    $trump = [
        'first name' => 'Donald',
        'last name' => 'Trump',
        'age' => 74,
    ];
    
    while (list($key, $info) = each($trump)){
        echo "$key: $info\r\n";
    }

    Trong ví dụ này, hàm each() lần lượt lấy từng phần tử của mảng. Nếu không còn phần tử nào, each() trả lại giá trị false. Ứng với mỗi phần tử chúng ta sử dụng hàm list() để tách nó ra thành phần khóa và thành phần giá trị.

    Từ PHP 7.2 khuyến nghị không sử dụng list() và each() nữa mà chỉ nên sử dụng foreach. Việc trình bày list() và each() ở đây chỉ mang tính giới thiệu nếu bạn đọc code viết cho các phiên bản cũ hơn.

    Xóa phần tử của mảng

    Hàm unset()

    Cách đơn giản nhất để xóa phần tử của mảng là sử dụng hàm unset() trên các phần tử cần xóa. Hãy xem ví dụ sau:

    $trump = [
        'first name' => 'Donald',
        'last name' => 'Trump',
        'age' => 74,
        'email' => 'trump@gmail.com',
        'phone' => '0123.456.789'
    ];
    
    var_dump($trump);
    unset($trump['age']); // xóa phần tử 'age'
    var_dump($trump);
    Kết quả var_dump ban đầu
    array(5) {
    'first name' =>
    string(6) "Donald"
    'last name' =>
    string(5) "Trump"
    'age' =>
    int(74)
    'email' =>
    string(15) "trump@gmail.com"
    'phone' =>
    string(12) "0123.456.789"
    }
    Kết qua var_dump sau khi xóa phần tử age
    array(4) {
    'first name' =>
    string(6) "Donald"
    'last name' =>
    string(5) "Trump"
    'email' =>
    string(15) "trump@gmail.com"
    'phone' =>
    string(12) "0123.456.789"
    }

    Như vậy, chỉ cần truy xuất được phần tử nào theo khóa/chỉ số, bạn sẽ có thể xóa bỏ nó khỏi mảng sử dụng hàm unset() giống như xóa bỏ một biến thông thường: unset($mảng[khóa|chỉ_số], ...); Hàm unset() nhận không giới hạn số lượng tham số nên bạn có thể đồng thời xóa bỏ nhiều phần tử của mảng.

    Đối với mảng chỉ số cần lưu ý: khi bạn unset() một phần tử, chỉ số của các phần tử khác không hề được tính lại. Do vậy nếu cần tính và sắp xếp lại chỉ số, bạn cần tự thực hiện thủ công.

    Ví dụ:

    $days = [2 => 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
    var_dump($days);
    unset($days[2], $days[4], $days[6], $days[8]);
    var_dump($days);
    Kết quả var_dump mảng $days ban đầu
    array(7) {
    [2] =>
    string(6) "Monday"
    [3] =>
    string(7) "Tuesday"
    [4] =>
    string(9) "Wednesday"
    [5] =>
    string(8) "Thursday"
    [6] =>
    string(6) "Friday"
    [7] =>
    string(8) "Saturday"
    [8] =>
    string(6) "Sunday"
    }
    Kết quả var_dump mảng $days sau khi bỏ đi các phần tử ở vị trí chẵn
    array(3) {
    [3] =>
    string(7) "Tuesday"
    [5] =>
    string(8) "Thursday"
    [7] =>
    string(8) "Saturday"
    }

    Bạn có thể thấy, sau khi xóa đi các phần tử ở vị trí chẵn, các phần tử còn lại giữ nguyên chỉ số. Đây là điều khác biệt nếu bạn từng quen thuộc với mảng ở các ngôn ngữ như C#.

    Hàm array_splice()

    Một cách khác bạn cũng thường gặp khi đọc các tài liệu về mảng trong PHP là sử dụng hàm array_splice(). Hãy xem ví dụ sau:

    $trump = [
        'first name' => 'Donald',
        'last name' => 'Trump',
        'age' => 74,
        'email' => 'trump@gmail.com',
        'phone' => '0123.456.789'
    ];
    array_splice($trump, 1, 2);
    var_dump($trump);
    array(3) {
    'first name' =>
    string(6) "Donald"
    'email' =>
    string(15) "trump@gmail.com"
    'phone' =>
    string(12) "0123.456.789"
    }

    Khi sử dụng hàm array_splice() bạn cung cấp offset (độ dịch/vị trí) và số lượng phần tử cần xóa. Trong ví dụ trên chúng ta yêu cầu xóa 2 phần tử từ vị trí số 1 – bao gồm ‘last name’ và ‘age’. Chú ý, vị trí của phần tử đầu tiên được tính là số 0.

    Khi sử dụng array_splice() với mảng chỉ số cần lưu ý, sau khi xóa phần tử, hàm này sẽ tự động tính lại chỉ số bắt đầu từ 0. Hãy xem ví dụ sau:

    $days = [2 => 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
    var_dump($days);
    array_splice($days, 1, 2);
    var_dump($days);
    Mảng ban đầu
    array(7) {
    [2] =>
    string(6) "Monday"
    [3] =>
    string(7) "Tuesday"
    [4] =>
    string(9) "Wednesday"
    [5] =>
    string(8) "Thursday"
    [6] =>
    string(6) "Friday"
    [7] =>
    string(8) "Saturday"
    [8] =>
    string(6) "Sunday"
    }
    Sau khi chạy array_splice()
    array(5) {
    [0] =>
    string(6) "Monday"
    [1] =>
    string(8) "Thursday"
    [2] =>
    string(6) "Friday"
    [3] =>
    string(8) "Saturday"
    [4] =>
    string(6) "Sunday"
    }

    Bạn có thể để ý thấy, ban đầu mảng $days có chỉ số xuất phát từ 2. Sau khi sử dụng array_splice(), chỉ số được tính lại bắt đầu từ 0 như một mảng chỉ số tiêu chuẩn.

    Tìm kiếm trong mảng

    Tìm kiếm là một trong những chức năng quan trọng và thường gặp trong quá trình làm việc với mảng. PHP cung cấp các hàm để tìm kiếm giá trị, tìm kiếm khóa, tìm kiếm phần tử.

    Xác định giá trị trong mảng, hàm in_array()

    Nếu cần xác định xem một giá trị có nằm trong một mảng hay không, bạn có thể sử dụng hàm in_array() theo cách sau:

    $numbers = [1, 3, 5, 7, '9', '11', '13'];
    echo in_array(13, $numbers) ? "Yes" : "No", "\r\n"; // Yes
    echo in_array('13', $numbers) ? "Yes" : "No"; // Yes
    

    Trong ví dụ trên chúng ta sử dụng hàm in_array() để kiểm tra xem giá trị 13 (số) và ’13’ (chuỗi) có nằm trong mảng $numbers hay không. Cả hai lệnh đều cho kết quả là ‘Yes’.

    Hàm in_array() sẽ duyệt mảng để lần lượt so sánh giá trị cần xác định với các phần tử. Quá trình so sánh này sử dụng phép toán ==. Như bạn đã học trong bài về biểu thức và phép toán trong PHP, phép == thực hiện type juggling – tự động chuyển đổi kiểu trước khi so sánh. Do vậy, giá trị ’13’ và 13 là tương tự nhau.

    Để in_array() sử dụng phép so sánh ===, bạn cần thêm tham số thứ ba giá trị TRUE như sau:

    $numbers = [1, 3, 5, 7, '9', '11', '13'];
    echo in_array(13, $numbers, true) ? "Yes" : "No", "\r\n"; // No, giờ 13 (số) khác với '13' (chuỗi)
    echo in_array('13', $numbers, true) ? "Yes" : "No"; // Yes

    Xác định khóa trong mảng, hàm array_key_exists(()

    Một tình huống khác là cần xác định xem một khóa đã được sử dụng trong mảng hay chưa. Để giải quyết, bạn có thể sử dụng hàm array_key_exists() như sau:

    $book = [
        'title' => 'PHP programming',
        'authors' => 'Trump D.',
        'publisher' => 'Washington',
        'year' => 2020
    ];
    echo array_key_exists('title', $book) ? "Key exists!" : "Key not found!"; // kết quả 'Key exists!'

    Tìm kiếm khóa theo giá trị, hàm array_search()

    Bạn biết giá trị của một phần tử và cần xác định khóa tương ứng của phần tử đó. Để giải quyết có thể sử dụng hàm array_search() như sau:

    $book = [
        'title' => 'PHP programming',
        'authors' => 'Trump D.',
        'publisher' => 'Washington',
        'year' => 2020
    ];
    echo array_search('Washington', $book); // kết quả 'publisher'

    Tương tự như in_array(), array_search() cũng duyệt và so sánh giá trị. Mặc định hàm sẽ so sánh bằng phép toán ==. Nếu cần so sánh bằng phép toán ===, bạn cần tham số thứ ba với giá trị TRUE.

    Một số thao tác khác với mảng

    Đếm số phần tử

    Để đếm số phần tử của mảng, bạn dùng hàm count():

    $days = [2 => 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
    echo "Mảng có ", count($days), " phần tử";
    Mảng có 7 phần tử

    Kiểm tra biến mảng

    Để kiểm tra xem một biến có phải là mảng hay không, bạn dùng hàm is_array():

    $days = [2 => 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
    echo is_array($days) ? "Là mảng" : "Không phải mảng";

    Sắp xếp mảng

    Để sắp xếp mảng bạn dùng hàm sort() – sắp xếp tăng dần, hoặc rsort() – sắp xếp giảm dần:

    $days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
    sort($days);
    foreach ($days as $d) echo $d, " ";
    echo "\r\n";
    rsort($days);
    foreach ($days as $d) echo $d, " ";

    Chú ý, sort() và rsort() tác động trực tiếp trên mảng chứ không tạo ra mảng mới. Các hàm này trả về true nếu sắp xếp thành công và false nếu gặp lỗi trong quá trình sắp xếp.

    Bạn cũng có thể cung cấp tham số thứ hai để yêu cầu cách sắp xếp: SORT_NUMERIC – xếp theo cách sắp xếp số, hoặc SORT_STRING – xếp theo cách sắp xếp chuỗi ký tự.

    Tráo phần tử ngẫu nhiên

    Bạn có thể tráo ngẫu nhiên các phần tử của mảng với hàm shuffle():

    shuffle($days); echo "\r\n";
    foreach ($days as $d) echo $d, " ";
    shuffle($days); echo "\r\n";
    foreach ($days as $d) echo $d, " ";
    shuffle($days); echo "\r\n";
    foreach ($days as $d) echo $d, " ";
    Saturday Monday Wednesday Sunday Tuesday Thursday Friday
    Thursday Monday Tuesday Sunday Friday Wednesday Saturday
    Sunday Saturday Thursday Monday Wednesday Tuesday Friday

    Chuyển mảng thành danh sách biến

    Đây là một tính năng khá đặc biệt của PHP. Trước hết hãy xem ví dụ sau:

    $trump = [
        'fname' => 'Donald',
        'lname' => 'Trump',
        'age' => 74,
        'email' => 'trump@gmail.com'
    ];
    extract($trump);
    echo "$fname, $lname, $age, $email";
    Donald, Trump, 74, trump@gmail.com

    Hàm extract() có khả năng đặc biệt: chuyển các cặp khóa => giá_trị của một mảng thành các biến có tên và giá trị tương ứng. Ví dụ, phần tử ‘fname’ sẽ chuyển thành biến $fname với giá trị ‘Donald’ tương ứng, phần tử ‘age’ chuyển thành biến $age với giá trị 74 tương ứng.

    Đây là một cách thức rất tiện lợi khi xử lý các tham số trong truy vấn GET và POST bạn sẽ gặp sau này.

    Chuyển danh sách biến thành mảng

    Đây là thao tác ngược lại của extract. Bạn có một danh sách biến và bạn muốn tạo ra một mảng từ danh sách biến này, theo đó tên biến thành khóa, giá trị của biến thành giá trị của phần tử tương ứng. Hãy xem ví dụ sau:

    $fname = "Doctor";
    $sname = "Who";
    $planet = "Gallifrey";
    $system = "Gridlock";
    $constellation = "Kasterborous";
    $contact = compact('fname', 'sname', 'planet', 'system', 'constellation');
    print_r($contact);
    Array
    (
    [fname] => Doctor
    [sname] => Who
    [planet] => Gallifrey
    [system] => Gridlock
    [constellation] => Kasterborous
    )

    Để ý rằng hàm compact() tạo ra mảng $contact từ các biến fname, sname, planet, system, và constellation.

    Kết luận

    Trong bài học này chúng ta đã học một số thao tác xử lý mảng cơ bản:

    • Để thêm phần tử mới vào mảng có thể sử dụng phép toán truy xuất phần tử. Nếu chỉ số/khóa chưa tồn tại, PHP sẽ thêm phần tử vào mảng.
    • Cũng có thể sử dụng hàm array_push() để thêm các phần tử vào cuối mảng.
    • Để duyệt mảng cần sử dụng lệnh lặp foreach.
    • Để xóa phần tử khỏi mảng cần sử dụng lệnh unset(). Khi xóa phần tử, chỉ số của các phần tử còn lại không thay đổi.
    • Để tìm kiếm trong mảng, tùy từng yêu cầu bạn có thể sử dụng hàm in_array(), array_key_exists(), hoặc array_search().
    • Bạn cũng có thể thực hiện các thao tác khác trên mảng, như đếm số phần tử count(), sắp xếp (sort() hoặc rsort()), chuyển đổi qua lại giữa mảng và danh sách biến (extract() hay compact()).

    + Nếu bạn thấy site hữu ích, trước khi rời đi hãy giúp đỡ site bằng một hành động nhỏ để site có thể phát triển và phục vụ bạn tốt hơn.
    + Nếu bạn thấy bài viết hữu ích, hãy giúp chia sẻ tới mọi người.
    + Nếu có thắc mắc hoặc cần trao đổi thêm, mời bạn viết trong phần thảo luận cuối trang.
    Cảm ơn bạn!

    Subscribe
    Notify of
    guest
    0 Thảo luận
    Inline Feedbacks
    View all comments