Voici ma solution très simple, compatible avec PHP 5.5:
function array_map_assoc(callable $f, array $a) {
return array_column(array_map($f, array_keys($a), $a), 1, 0);
}
L'appelable que vous fournissez doit lui-même renvoyer un tableau avec deux valeurs, c'est-à-dire return [key, value]. L'appel interne à array_mapproduit donc un tableau de tableaux. Celui-ci est ensuite reconverti en un tableau à une dimension par array_column.
Usage
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k, 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Production
array(3) {
["new first"]=>
string(7) "new 1st"
["new second"]=>
string(7) "new 2nd"
["new third"]=>
string(7) "new 3rd"
}
Application partielle
Dans le cas où vous devez utiliser la fonction plusieurs fois avec des tableaux différents mais la même fonction de mappage, vous pouvez faire quelque chose appelé application de fonction partielle (liée au `` currying ''), qui vous permet de ne transmettre le tableau de données qu'à l'invocation:
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));
Qui produit la même sortie, donnée $funcet $ordinalssont comme précédemment.
REMARQUE: si votre fonction mappée renvoie la même clé pour deux entrées différentes, la valeur associée à la dernière clé gagnera. Inversez le tableau d'entrée et le résultat de sortie array_map_assocpour permettre aux clés antérieures de gagner. (Les clés renvoyées dans mon exemple ne peuvent pas entrer en collision car elles incorporent la clé du tableau source, qui à son tour doit être unique.)
Alternative
Voici une variante de ce qui précède, qui pourrait s'avérer plus logique pour certains, mais nécessite PHP 5.6:
function array_map_assoc(callable $f, array $a) {
return array_merge(...array_map($f, array_keys($a), $a));
}
Dans cette variante, votre fonction fournie (sur laquelle le tableau de données est mappé) devrait plutôt renvoyer un tableau associatif avec une ligne, c'est-à-dire return [key => value]. Le résultat du mappage de l'appelable est ensuite simplement décompressé et transmis à array_merge. Comme précédemment, le retour d'une clé en double entraînera la victoire des valeurs ultérieures.
nb Alex83690 a noté dans un commentaire que l'utilisation array_replaceici à la place de array_mergepréserverait les clés entières. array_replacene modifie pas le tableau d'entrée, est donc sans danger pour le code fonctionnel.
Si vous utilisez PHP 5.3 à 5.5, ce qui suit est équivalent. Il utilise array_reduceet l' +opérateur de tableau binaire pour convertir le tableau bidimensionnel résultant en un tableau unidimensionnel tout en préservant les clés:
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;
}, []);
}
Usage
Ces deux variantes seraient utilisées ainsi:
$ordinals = [
'first' => '1st',
'second' => '2nd',
'third' => '3rd',
];
$func = function ($k, $v) {
return ['new ' . $k => 'new ' . $v];
};
var_dump(array_map_assoc($func, $ordinals));
Notez le =>au lieu de ,dans $func.
La sortie est la même qu'avant, et chacune peut être partiellement appliquée de la même manière qu'auparavant.
Résumé
Le but de la question d'origine est de rendre l'appel de l'appel aussi simple que possible, au détriment d'avoir une fonction plus compliquée qui est invoquée; en particulier, pour pouvoir passer le tableau de données en un seul argument, sans diviser les clés et les valeurs. En utilisant la fonction fournie au début de cette réponse:
$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)));
Ou, pour cette question uniquement, nous pouvons faire une simplification de la array_map_assoc()fonction qui supprime les clés de sortie, car la question ne les demande pas:
$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));
Donc, la réponse est NON , vous ne pouvez pas éviter d'appeler array_keys, mais vous pouvez faire abstraction de l'endroit où array_keysest appelé une fonction d'ordre supérieur, ce qui pourrait être suffisant.