Hướng dẫn dùng map method trong PHP

Hàm array_map() sẽ lặp tất cả các phần tử của mảng và truyền vào hàm callback định nghĩa trước đó của người dùng. Hàm callback sẽ coi các phần từ của mảng như là những tham số và nó sẽ lặp lại cho đến khi tất cả các phần tử của mảng đã được truyền vào.

Hướng dẫn dùng map method trong PHP

Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Cú pháp

Cú pháparray_map($func, $arr1, $arr2 ...);

Trong đó:

  • $func là hàm do người dùng định nghĩa sẽ nhận các phần tử truyền vào là các phần tử của $arr1, $arr2...
  • $arr1, $arr2 ... là các mảng dữ liệu truyền vào.

Ví dụ

Code

function show($name, $age){
	echo 'tên của tôi là ' . $name . ', tôi ' . $age . ' tuổi<br />';
}
$name = [
	'Minh',
	'Peter',
	'John'
];
$age  = [
	21,
	23,
	45
];
array_map('show', $name, $age);		

Kết quả

tên của tôi là Minh, tôi 21 tuổi
tên của tôi là Peter, tôi 23 tuổi
tên của tôi là John, tôi 45 tuổi

Tham khảo: php.net

Bài viết này được đăng tại [free tuts .net]

Ba khái niệm map, filter và reduce rất phổ biến và hay dùng trong Functional Programming (lập trình hàm). Nhưng với lập trình viên PHP, một ngôn ngữ có thể gọi là khá hổ lốn thì có thể bạn chưa bao giờ nghe tới hoặc biết nhưng chẳng bao giờ dùng.

Và những ai không dùng ba operations trên thì thường phải viết những đoạn code bốc smell như foreach lồng nhau, dùng mảng tạm, nhân đôi một mảng hay thay đổi giá trị của mảng đó khi không cần thiết.

Tại sao phải dùng map, filter và reduce

Ở lập trình hàm, lập trình viên không được đổi giá trị của variable và cũng không dùng vòng lặp. Thay vào đó họ dùng map, filter và reduce để:

  1. thay đổi hàng loạt
  2. lọc
  3. tính toán

dựa trên các thành phần trong mảng mà không cần thay đổi giá trị của chúng. Hơn nữa, ba operations trên không chỉ dùng trong lập trình hàm, chúng còn dùng để rút gọn code, làm code minh bạch hơn và ít smell hơn. Ví dụ với một bài toán đơn giản:

Cho một mảng số int ở dạng chuỗi, biến nó thành mảng số int

Dùng foreach ta sẽ có code như sau:

$strings = ['1', '2', '3', '999']; // mảng string
$ints = [];
foreach ($strings as $string) {
    $ints[] = intval($string); // thêm lần lượt các giá trị int cho mảng tạm
}

var_dump($ints); // [1, 2, 3, 999]

Nhưng với array_map thì code chỉ còn có thế này:

$strings = ['1', '2', '3', '999'];
// map hàm intval với từng phần tử trong mảng $strings
$ints = array_map('intval', $strings);

var_dump($ints); // [1, 2, 3, 999]

Ngắn gọn hơn nhiều rồi đúng không? Tiếp theo tôi sẽ giới thiệu chi tiết từng operator một.

Map của PHP – array_map

Hướng dẫn dùng map method trong PHP

Nói một cách “hàn lâm” thì array_map trả về mảng đầu vào với các phần tử đã được xử lý qua một hàm callback. Usage:

array array_map ( callable $callback , array $array1 [, array $... ] )

Ta cùng tìm hiểu nó hoạt động như thế nào qua hai ví dụ thực tiễn.

Ví dụ 1:

Tạo một mảng có giá trị gấp đôi mảng int có sẵn

Dùng foreach:

$numbers = [1, 2, 3];
$x2Numbers = [];
foreach ($numbers as $number) {
    $x2Numbers[] = 2 * $number;
}

var_dump($x2Numbers); // [2, 4 ,6]

Dùng array_map:

$numbers = [1, 2, 3];
$x2Numbers = array_map(function ($value) {
    return $value * 2;
}, $numbers);

var_dump($x2Numbers); // [2, 4 ,6]

Ví dụ 2:

Ta có một mảng objects chứa điểm và tên của các sinh viên, dựa vào điểm ta cập nhật phần đánh giá học lực của sinh viên được chia làm 4 loại:
0 <= score <= 4 Loại F
4 < score <= 6 Loại D
6 < score <= 7 Loại C
7 < score < 8 Loại B
8 <= score <= 10 Loại A

Class Student:

class Student{
    public $name; // tên string
    public $score; // điểm float
    public $grade; // xếp hạng string
}

Dữ liệu đầu vào:

array(3) {
  [0]=>
  object(Student)#1 (3) {
    ["name"]=>
    string(9) "Student 1"
    ["score"]=>
    float(2.5)
    ["grade"]=>
    NULL
  }
  [1]=>
  object(Student)#2 (3) {
    ["name"]=>
    string(9) "Student 2"
    ["score"]=>
    float(7.6)
    ["grade"]=>
    NULL
  }
  [2]=>
  object(Student)#3 (3) {
    ["name"]=>
    string(9) "Student 3"
    ["score"]=>
    int(9)
    ["grade"]=>
    NULL
  }
}

Phần này tôi sẽ không viết code ví dụ bằng foreach nữa mà sẽ dùng array_map luôn:

function setGrade($student)
{
    if ($student->score >= 8) {
        $student->grade = 'A';
    } elseif ($student->score > 7) {
        $student->grade = 'B';
    } elseif ($student->score > 6) {
        $student->grade = 'C';
    } elseif ($student->score > 4) {
        $student->grade = 'D';
    } else {
        $student->grade = 'F';
    }
    return $student;
}

// map từng phần tử của mảng $students với hàm setGrade
array_map('setGrade', $students);

Kết quả là các sinh viên đã được xếp loại:

array(3) {
  [0]=>
  object(Student)#1 (3) {
    ["name"]=>
    string(9) "Student 1"
    ["score"]=>
    float(2.5)
    ["grade"]=>
    string(1) "F"
  }
  [1]=>
  object(Student)#2 (3) {
    ["name"]=>
    string(9) "Student 2"
    ["score"]=>
    float(7.6)
    ["grade"]=>
    string(1) "B"
  }
  [2]=>
  object(Student)#3 (3) {
    ["name"]=>
    string(9) "Student 3"
    ["score"]=>
    int(9)
    ["grade"]=>
    string(1) "A"
  }
}

Với cách code trên ta còn tận dụng được hàm setGrade để dùng lại nhiều lần. Bản thân tôi luôn cố gắng viết hàm hay class để dùng lại cho dù có mất nhiều thời gian hơn.

Từ giờ khi bạn muốn làm một tác vụ giống nhau với từng phần tử trong mảng, thay vì dùng foreach thì hãy suy nghĩ cách dùng array_map nhé. Để tìm hiểu chi tiết hơn bạn có thể tham khảo manual của array_map tại đây.

Vậy là phần 1 đã kết thúc, mời bạn đọc tiếp phần 2 để cùng tìm hiểu về array_filter.

4.8 4 votes

Article Rating

Jared Chu

Full-time Freelancer | Web Developer (WordPress / Magento / Laravel)