Ось моє дуже просте, сумісне з PHP 5.5 рішення:
function array_map_assoc(callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
}
Викликаний, який ви надаєте, повинен сам повертати масив з двома значеннями, тобто return [key, value]
. Отже, внутрішній виклик array_map
виробляє масив масивів. Потім це конвертується назад в одновимірний масив array_column
.
Використання
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k, 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Вихідні дані
array(3) {
["new first"]=>
string(7) "new 1st"
["new second"]=>
string(7) "new 2nd"
["new third"]=>
string(7) "new 3rd"
}
Часткове застосування
Якщо вам потрібно багато разів використовувати функцію з різними масивами, але однакову функцію відображення, ви можете зробити щось, що називається додатком часткової функції (пов’язаним з ' currying '), що дозволяє передавати масив даних лише після виклику:
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));
Який виробляє такий же результат, враховуючи $func
і $ordinals
є такими , як раніше.
ПРИМІТКА: якщо ваша картографічна функція повертає одну і ту ж клавішу для двох різних входів, значення, пов'язане з пізнішим ключем, виграє. Зворотний вхідний масив і результат виводу, array_map_assoc
щоб дозволити виграти більш ранні клавіші. (Повернені ключі в моєму прикладі не можуть зіткнутися, оскільки вони містять ключ вихідного масиву, який, в свою чергу, повинен бути унікальним.)
Альтернатива
Далі йде варіант вищезазначеного, який може виявитися більш логічним для деяких, але вимагає PHP 5.6:
function array_map_assoc(callable $f, array $a) {
return array_merge(...array_map($f, array_keys($a), $a));
}
У цьому варіанті надана функція (над якою відображається масив даних) повинна замість цього повертати асоціативний масив з одним рядком, тобто return [key => value]
. Результат відображення відображуваного дзвінка просто розпаковується та передається array_merge
. Як і раніше, повернення дубліката ключа призведе до виграшу пізніших значень.
nb Alex83690 зазначив у коментарі, що використання array_replace
тут замість array_merge
збереже цілі клавіші. array_replace
не змінює вхідний масив, тому безпечний для функціонального коду.
Якщо ви перебуваєте на PHP 5.3 до 5.5, наступне еквівалентно. Він використовує array_reduce
і +
оператор двійкового масиву для перетворення отриманого двовимірного масиву вниз до одновимірного масиву, зберігаючи ключі:
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;
}, []);
}
Використання
Обидва ці варіанти будуть використані таким чином:
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k => 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Зауважте =>
замість ,
in $func
.
Вихід такий же, як і раніше, і кожен може бути частково застосований так само, як і раніше.
Підсумок
Мета оригінального запитання - зробити виклик якомога простішим за рахунок наявності більш складної функції, яка викликається; особливо мати можливість передавати масив даних як єдиний аргумент, не розбиваючи ключі та значення. Використовуючи функцію, надану на початку цієї відповіді:
$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)));
Або, лише для цього питання, ми можемо зробити спрощення array_map_assoc()
функціонування, яке скидає вихідні клавіші, оскільки питання не запитує їх:
$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));
Отже, відповідь " НІ" , ви не можете уникнути дзвінків array_keys
, але ви можете абстрагувати місце, куди array_keys
викликується, функцію вищого порядку, яка може бути досить хорошою.