Đây là giải pháp tương thích PHP 5.5 rất đơn giản của tôi:
function array_map_assoc(callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
}
Có thể gọi được mà bạn cung cấp sẽ trả về một mảng có hai giá trị, nghĩa là return [key, value]
. array_map
Do đó, cuộc gọi bên trong để tạo ra một mảng các mảng. Điều này sau đó được chuyển đổi trở lại một mảng một chiều bằng array_column
.
Sử dụng
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k, 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Đầu ra
array(3) {
["new first"]=>
string(7) "new 1st"
["new second"]=>
string(7) "new 2nd"
["new third"]=>
string(7) "new 3rd"
}
Ứng dụng một phần
Trong trường hợp bạn cần sử dụng hàm nhiều lần với các mảng khác nhau nhưng cùng một hàm ánh xạ, bạn có thể thực hiện một thứ gọi là ứng dụng hàm một phần (liên quan đến ' currying '), cho phép bạn chỉ truyền vào mảng dữ liệu khi gọi:
function array_map_assoc_partial(callable $f) {
return function (array $a) use ($f) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
};
}
...
$my_mapping = array_map_assoc_partial($func);
var_dump($my_mapping($ordinals));
Mà tạo ra cùng một đầu ra, được đưa ra $func
và $ordinals
như trước đó.
LƯU Ý: nếu chức năng được ánh xạ của bạn trả về cùng một khóa cho hai đầu vào khác nhau, giá trị được liên kết với khóa sau sẽ giành chiến thắng. Đảo ngược mảng đầu vào và kết quả đầu ra của array_map_assoc
để cho phép các khóa trước đó giành chiến thắng. (Các khóa được trả về trong ví dụ của tôi không thể va chạm vì chúng kết hợp khóa của mảng nguồn, lần lượt phải là duy nhất.)
Thay thế
Sau đây là một biến thể của những điều trên, có thể chứng minh logic hơn đối với một số người, nhưng yêu cầu PHP 5.6:
function array_map_assoc(callable $f, array $a) {
return array_merge(...array_map($f, array_keys($a), $a));
}
Trong biến thể này, hàm được cung cấp của bạn (qua đó mảng dữ liệu được ánh xạ) thay vào đó sẽ trả về một mảng kết hợp với một hàng, tức là return [key => value]
. Kết quả của ánh xạ có thể gọi được sau đó chỉ đơn giản là giải nén và chuyển đến array_merge
. Như trước đó, trả lại một khóa trùng lặp sẽ dẫn đến chiến thắng giá trị sau này.
nb Alex83690 đã lưu ý trong một nhận xét rằng sử dụng array_replace
ở đây thay cho việc array_merge
bảo tồn các khóa nguyên. array_replace
không sửa đổi mảng đầu vào, vì vậy an toàn cho mã chức năng.
Nếu bạn đang dùng PHP 5.3 đến 5.5, thì sau đây là tương đương. Nó sử dụng array_reduce
và +
toán tử mảng nhị phân để chuyển đổi mảng hai chiều kết quả thành mảng một chiều trong khi bảo quản các khóa:
function array_map_assoc(callable $f, array $a) {
return array_reduce(array_map($f, array_keys($a), $a), function (array $acc, array $a) {
return $acc + $a;
}, []);
}
Sử dụng
Cả hai biến thể này sẽ được sử dụng như vậy:
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k => 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Lưu ý =>
thay vì ,
trong $func
.
Đầu ra giống như trước đây và mỗi cái có thể được áp dụng một phần theo cùng một cách như trước đây.
Tóm lược
Mục tiêu của câu hỏi ban đầu là làm cho việc gọi cuộc gọi trở nên đơn giản nhất có thể, với chi phí có một chức năng phức tạp hơn được gọi; đặc biệt, để có khả năng truyền mảng dữ liệu dưới dạng một đối số, mà không cần tách các khóa và giá trị. Sử dụng chức năng được cung cấp khi bắt đầu câu trả lời này:
$test_array = ["first_key" => "first_value",
"second_key" => "second_value"];
$array_map_assoc = function (callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
};
$f = function ($key, $value) {
return [$key, $key . ' loves ' . $value];
};
var_dump(array_values($array_map_assoc($f, $test_array)));
Hoặc, chỉ cho câu hỏi này, chúng tôi có thể đơn giản hóa array_map_assoc()
chức năng bỏ các phím đầu ra, vì câu hỏi không yêu cầu chúng:
$test_array = ["first_key" => "first_value",
"second_key" => "second_value"];
$array_map_assoc = function (callable $f, array $a) {
return array_map($f, array_keys($a), $a);
};
$f = function ($key, $value) {
return $key . ' loves ' . $value;
};
var_dump($array_map_assoc($f, $test_array));
Vì vậy, câu trả lời là KHÔNG , bạn không thể tránh gọi array_keys
, nhưng bạn có thể trừu tượng ra nơi array_keys
được gọi vào hàm bậc cao hơn, có thể đủ tốt.