Inilah solusi PHP 5.5-kompatibel saya yang sangat sederhana:
function array_map_assoc(callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
}
Callable yang Anda berikan harus mengembalikan array dengan dua nilai, yaitu return [key, value]
. Karena itu panggilan batin untuk array_map
menghasilkan array array. Ini kemudian akan dikonversi kembali ke array dimensi tunggal oleh array_column
.
Pemakaian
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k, 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Keluaran
array(3) {
["new first"]=>
string(7) "new 1st"
["new second"]=>
string(7) "new 2nd"
["new third"]=>
string(7) "new 3rd"
}
Aplikasi sebagian
Jika Anda perlu menggunakan fungsi berkali-kali dengan array yang berbeda tetapi fungsi pemetaan yang sama, Anda bisa melakukan sesuatu yang disebut aplikasi fungsi parsial (terkait dengan ' currying '), yang memungkinkan Anda untuk hanya memasukkan array data setelah doa:
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));
Yang menghasilkan output yang sama, diberikan $func
dan $ordinals
sama seperti sebelumnya.
CATATAN: jika fungsi Anda yang dipetakan mengembalikan kunci yang sama untuk dua input berbeda, nilai yang terkait dengan kunci nanti akan menang. Membalikkan array input dan hasil output array_map_assoc
untuk memungkinkan kunci sebelumnya untuk menang. (Kunci yang dikembalikan dalam contoh saya tidak dapat bertabrakan karena mereka memasukkan kunci dari array sumber, yang pada gilirannya harus unik.)
Alternatif
Berikut ini adalah varian di atas, yang mungkin terbukti lebih logis untuk beberapa orang, tetapi membutuhkan PHP 5.6:
function array_map_assoc(callable $f, array $a) {
return array_merge(...array_map($f, array_keys($a), $a));
}
Dalam varian ini, fungsi yang disediakan Anda (di mana array data dipetakan) akan mengembalikan array asosiatif dengan satu baris, yaitu return [key => value]
. Hasil pemetaan callable kemudian dibongkar dan diteruskan ke array_merge
. Seperti sebelumnya, mengembalikan kunci duplikat akan menghasilkan nilai yang menang kemudian.
nb Alex83690 telah mencatat dalam komentar bahwa menggunakan array_replace
di sini sebagai pengganti array_merge
akan mempertahankan kunci integer. array_replace
tidak memodifikasi array input, jadi aman untuk kode fungsional.
Jika Anda menggunakan PHP 5.3 hingga 5.5, yang berikut ini setara. Ini menggunakan array_reduce
dan +
operator array biner untuk mengkonversi array dua dimensi yang dihasilkan ke array satu dimensi sambil mempertahankan kunci:
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;
}, []);
}
Pemakaian
Kedua varian ini akan digunakan sebagai berikut:
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k => 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Perhatikan =>
bukan ,
di $func
.
Outputnya sama seperti sebelumnya, dan masing-masing dapat diterapkan sebagian dengan cara yang sama seperti sebelumnya.
Ringkasan
Tujuan dari pertanyaan awal adalah untuk membuat doa panggilan sesederhana mungkin, dengan mengorbankan fungsi yang lebih rumit yang dipanggil; khususnya, untuk memiliki kemampuan untuk melewatkan array data sebagai argumen tunggal, tanpa memisahkan kunci dan nilai. Menggunakan fungsi yang disediakan di awal jawaban ini:
$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)));
Atau, hanya untuk pertanyaan ini, kita dapat menyederhanakan array_map_assoc()
fungsi yang menjatuhkan kunci output, karena pertanyaan tidak menanyakannya:
$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));
Jadi jawabannya adalah TIDAK , Anda tidak bisa menghindari panggilan array_keys
, tetapi Anda bisa mengabstraksikan tempat di mana array_keys
dipanggil menjadi fungsi tingkat tinggi, yang mungkin cukup baik.