İşte benim çok basit, PHP 5.5 uyumlu çözümüm:
function array_map_assoc(callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
}
Sağladığınız çağrılabilirin kendisi iki değere sahip bir dizi döndürmelidir return [key, value]
. Bu array_map
nedenle iç çağrı , bir dizi dizi üretir. Bu daha sonra tarafından tek boyutlu bir diziye geri dönüştürülür array_column
.
kullanım
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k, 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Çıktı
array(3) {
["new first"]=>
string(7) "new 1st"
["new second"]=>
string(7) "new 2nd"
["new third"]=>
string(7) "new 3rd"
}
Kısmi uygulama
İşlevi farklı dizilerle ancak aynı eşleme işleviyle birçok kez kullanmanız gerekirse, yalnızca çağırma üzerine veri dizisine geçmenize izin veren kısmi işlev uygulaması (' currying ' ile ilgili) olarak adlandırılan bir şey yapabilirsiniz :
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));
Hangi aynı çıktıyı verir, verilen $func
ve $ordinals
daha önceki gibi.
NOT: eşlenen işleviniz iki farklı giriş için aynı anahtarı döndürürse , sonraki anahtarla ilişkili değer kazanacaktır. array_map_assoc
Daha önceki anahtarların kazanmasına izin vermek için giriş dizisini ve çıkış sonucunu tersine çevirin . (Örneğimdeki döndürülen anahtarlar, kaynak dizinin anahtarını içerdiklerinden çakışamazlar; bu da benzersiz olmalıdır.)
Alternatif
Aşağıda, bazıları için daha mantıklı olabilecek, ancak PHP 5.6 gerektiren bir varyant yer almaktadır:
function array_map_assoc(callable $f, array $a) {
return array_merge(...array_map($f, array_keys($a), $a));
}
Bu varyantta, sağladığınız işlev (üzerinde veri dizisinin eşlendiği), bunun yerine bir satırla ilişkilendirilebilir bir dizi döndürmelidir return [key => value]
. Çağrılabilir eşlemenin sonucu daha sonra paketten çıkarılır ve iletilir array_merge
. Daha önce olduğu gibi, yinelenen bir anahtarın döndürülmesi sonraki değerlerin kazanılmasına neden olacaktır.
nb Alex83690 bir yorumda, array_replace
bunun yerine burada array_merge
tamsayı anahtarlarının korunacağını belirtti. array_replace
giriş dizisini değiştirmez, bu nedenle işlevsel kod için güvenlidir.
PHP 5.3 ile 5.5 arasındaysanız, aşağıdakine denktir. Anahtarları korurken elde edilen iki boyutlu diziyi tek boyutlu bir diziye dönüştürmek için array_reduce
ve ikili +
dizi operatörünü kullanır :
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;
}, []);
}
kullanım
Bu değişkenlerin her ikisi de şu şekilde kullanılır:
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k => 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Not =>
yerine ,
de $func
.
Çıktı öncekiyle aynıdır ve her biri eskisi gibi kısmen uygulanabilir.
özet
Orijinal sorunun amacı, çağrının çağrılmasını mümkün olduğunca basit hale getirmek ve çağrılmış daha karmaşık bir işleve sahip olmaktır; özellikle, veri dizisini anahtarları ve değerleri bölmeden tek bir argüman olarak iletme yeteneğine sahip olmak. Bu cevabın başında verilen işlevi kullanarak:
$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)));
Veya yalnızca bu soru için, array_map_assoc()
çıkış anahtarları bırakan işlev için basitleştirme yapabiliriz , çünkü soru bunları sormaz:
$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));
Yani cevap HAYIR , aramaktan kaçınamazsınız array_keys
, ancak array_keys
yeterince iyi olabilecek daha üst düzey bir fonksiyona çağrılan yeri soyutlayabilirsiniz .