PHP array_map y compris les touches
Est-il un moyen de faire quelque chose comme ceci:
$test_array = array("first_key" => "first_value",
"second_key" => "second_value");
var_dump(array_map(function($a, $b) { return "$a loves $b"; },
array_keys($test_array),
array_values($test_array)));
Mais au lieu d'appeler array_keys
et array_values
, directement en passant la $test_array
variable?
La sortie désirée est:
array(2) {
[0]=>
string(27) "first_key loves first_value"
[1]=>
string(29) "second_key loves second_value"
}
Vous devez vous connecter pour publier un commentaire.
Pas avec array_map, comme il ne gère pas les clés.
array_walk n':
Il change le tableau donné en paramètre cependant, il n'est donc pas exactement de la programmation fonctionnelle (que vous avez de la question étiqueté comme ça). Aussi, comme l'a souligné dans les commentaires, cela ne fera que modifier les valeurs de la matrice, de sorte que les touches ne seront pas ce que vous avez spécifié dans la question.
Vous pouvez écrire une fonction qui corrige les points au-dessus de vous-même si vous voulez, comme ceci:
$a = "$b loves $a"
, pour correspondre à l'OP de sortie souhaité.array_walk()
ne pas retourner le tableau qui en résulte, mais un bool place.array:2 [ "first_key" => "first_key loves first_value" "second_key" => "second_key loves second_value" ]
C'est sans doute le plus court et le plus facile de raisonner sur:
array_keys()
. Cela semble comme une bête exigence, cependant.Voici mon très simple, PHP 5.5-une solution compatible:
Remboursables que vous fournissez doit retourner un tableau avec deux valeurs, c'est à dire
return [key, value]
. L'appel intérieur àarray_map
produit donc un tableau de tableaux. Cela devient alors de nouveau converti en tableau à une seule dimension pararray_column
.D'utilisation
De sortie
Application partielle
Dans le cas où vous avez besoin d'utiliser la fonction de nombreuses fois avec d'autres tableaux, mais la même fonction de mapping, vous pouvez faire quelque chose appelé partielle de la fonction de demande (lié aunourrissage"), qui permet de passer dans le tableau de données lors de l'invocation:
Qui produit le même résultat, étant donné
$func
et$ordinals
sont comme précédemment.REMARQUE: si votre mappé fonction renvoie la même clé pour deux entrées différentes, la valeur associée à le plus tard clé de la victoire. Inverser le tableau d'entrée et de sortie de la suite de
array_map_assoc
pour permettre clés pour gagner. (Le retour de l'clés dans mon exemple ne peut pas entrer en collision puisqu'elles intègrent la touche de la source matrice, ce qui à son tour doit être unique.)Alternative
Suivant est une variante de ce qui précède, ce qui peut s'avérer plus logique pour certains, mais nécessite PHP 5.6:
Dans cette variante, votre fonction fournie (sur lequel le tableau de données est mappé) devrait plutôt retourner un tableau associatif avec une ligne, c'est à dire
return [key => value]
.Le résultat de la cartographie de la appelable est alors simplement déballé et transmis à
array_merge
. Comme précédemment, le retour d'un double de la clé entraînera plus tard, les valeurs de la réussite.Si vous êtes sur PHP 5.3 à 5.5, le suivant est équivalent. Il utilise
array_reduce
et le binaire+
de la matrice de l'opérateur de convertir la résultante de deux dimensions de la matrice de down d'un tableau à une dimension tout en préservant clés:D'utilisation
Ces deux variantes seraient utilisés ainsi:
Note le
=>
au lieu de,
dans$func
.Le résultat est le même qu'avant, et chacun peut être partiellement appliquées de la même manière qu'avant.
Résumé
Le but de la question d'origine est de faire de l'invocation de l'appel d'aussi simple que possible, au détriment de la plus compliquée de la fonction qui est appelé; en particulier, avoir la capacité de transmettre le tableau de données dans un seul argument, sans fractionnement les clés et les valeurs. À l'aide de la fonction fournie au début de cette réponse:
Ou, pour cette question seulement, on peut faire une simplification
array_map_assoc()
fonction que les gouttes de sortie touches, puisque la question ne demande pas pour eux:Donc la réponse est PAS, vous ne pouvez pas éviter d'appeler
array_keys
, mais vous pouvez abstraction de l'endroit oùarray_keys
est appelée dans une fonction d'ordre supérieur, qui pourrait être assez bon.array_column
PHP 5.5+, de telle sorte que cette réponse n'est pas compatible avec PHP 5.3array_merge
pararray_replace
pour préserver les touches qui serait entiers.function array_map_assoc(callable $f, array $a) { return array_merge(...array_map(function ($k, $v) use ($f) { return [ $k => $f($k, $v) ]; }, array_keys($a), $a)); }
. Pour que cela fonctionne, le$f
doit être enveloppé avec une autre fonction, que les cartes de la nouvelle valeur de[key=>new_value]
.Avec PHP5.3 ou plus tard:
C'est de cette façon que j'ai mis en œuvre ce dans mon projet.
Basé sur la réponse de l'éie, voici ce que j'ai finalement fait afin d'éviter de gâcher le tableau d'origine:
array_walk
que vous n'êtes pas référence à la fermeture.Par le "manuel de la boucle" je voulais écrire une fonction personnalisée qui utilise
foreach
. Cela renvoie un nouveau tableau commearray_map
n'parce que la fonction de l'étendue des causes$array
être un copier—pas une référence:Votre technique à l'aide de
array_map
avecarray_keys
quoique, en réalité, semble plus simple et plus puissant parce que vous pouvez utilisernull
comme un rappel pour retourner les paires clé-valeur:unset( $value )
parce qu'il existe toujours dans les limites définies.YaLinqo bibliothèque* est bien adapté pour ce genre de tâches. C'est un port de LINQ de .NET qui soutient pleinement les valeurs et les clés dans tous les rappels et ressemble à SQL. Par exemple:
ou tout simplement:
Ici,
'"$k loves $v"'
est un raccourci pour la fermeture complète de la syntaxe qui cette bibliothèque prend en charge.toArray()
dans la fin est facultative. La méthode de la chaîne retourne un itérateur, donc si le résultat doit être itéré à l'aide deforeach
,toArray
appel peut être supprimé.* développé par moi
J'ai fait cette fonction, basée sur la réponse de l'éie:
Exemple:
De sortie:
Bien sûr, vous pouvez utiliser
array_values
pour revenir exactement ce que l'OP veut.$arr
est de type array, cependant, si vous tapez-indicateur de vos arguments commecallable
etarray
vous pouvez au lieu de déposer le chèque àis_callable
. Ensuite, vous faites une cession à $valeur qui est ensuite utilisé. Vous devez ignorer la valeur de retour. Troisièmement, il serait préférable de lancer une exception dans le rappel que de fausse déclaration. Vous pouvez alors soit toujours retourner une valeur valide ou toujours jeter.Je ferais quelque chose comme ceci:
Résultats:
Regardez ici! Il y a une solution triviale!
Comme indiqué dans la question,
array_map
a déjà exactement les fonctionnalités nécessaires. Les autres réponses ici sérieusement compliquer les choses:array_walk
n'est pas fonctionnelle.Utilisation
Exactement comme vous le souhaitez à partir de votre exemple:
Je vais ajouter encore une autre solution pour le problème à l'aide de la version 5.6 ou plus tard. Ne sais pas si c'est plus efficace que la déjà grande des solutions (probablement pas), mais pour moi, c'est juste plus simple à lire:
À l'aide de
strval()
comme un exemple de fonction dans learray_map
, cela va générer:J'espère que je ne suis pas le seul qui trouve que c'est assez simple à comprendre.
array_combine
crée unkey => value
tableau à partir d'un tableau de clés et un tableau de valeurs, le reste est assez explicite.Je vois qu'il en manque la réponse évidente:
Fonctionne exactement comme array_map. Presque.
En fait, il n'est pas pur
map
comme vous le savez à partir d'autres langues. Php est très bizarre, il ne nécessite certaines très bizarre fonctions de l'utilisateur, pour que nous ne voulons pas unbreak nos précisément casséworse is better
approche.Vraiment, ce n'est pas vraiment
map
à tous. Pourtant, il est toujours très utile.Première différence évidente de array_map, est que le rappel prend des sorties de
each()
de chaque tableau d'entrée au lieu de la valeur à lui seul. Vous pouvez toujours parcourir plusieurs tableaux à la fois.Deuxième différence est la façon dont la clé est traité après il est retourné à partir de rappel; la valeur de retour de fonction de callback doit être
array('new_key', 'new_value')
. Les touches peuvent être modifiées, même les touches peut même causer la valeur précédente d'être remplacé, même si la clé a été retourné. Ce n'est pas communmap
comportement, mais il vous permet de réécrire les touches.Troisième étrange c'est que, si vous omettez
key
en valeur de retour (soit pararray(1 => 'value')
ouarray(null, 'value')
), une nouvelle clé va être affecté, comme si$array[] = $value
a été utilisé. Ce n'est pasmap
's d'un comportement commun, et il est très utile parfois, je suppose.Quatrième étrange c'est que, si la fonction de rappel de la fonction ne renvoie pas de valeur, ou retourne
null
, l'ensemble des courants de clés et de valeurs est omis de la sortie, c'est tout simplement ignorée. Cette fonctionnalité est totalement nations uniesmap
py, mais il serait de rendre cette fonction super stunt double pourarray_filter_assoc
, si il y avait une telle fonction.Si vous omettez deuxième élément (
1 => ...
) (le valeur partie) dans le rappel du retour,null
est utilisée au lieu de la valeur réelle.D'autres éléments à l'exception de ceux avec des touches de
0
et1
dans le rappel de retour sont ignorés.Et enfin, si lambda renvoie une valeur quelconque à l'exception de
null
ou un tableau, elle est traitée comme si à la fois la clé et la valeur ont été omises, de telle sorte:null
est utilisé comme valeurREMARQUE:
Contrairement à
array_map
, tous les non-matrice de paramètres passés àarray_map_assoc
, à l'exception du premier paramètre de rappel, sont silencieusement coulé à des tableaux.EXEMPLES:
//TODO: examples, anyone?
J'aime toujours le javascript variante de la matrice de la carte. La version la plus simple serait:
Alors maintenant, vous pouvez simplement passer d'une fonction de rappel de la façon de construire les valeurs.
h(g(f($data)))
s'appliquef
, puisg
, puish
à vos données. Il est généralement considéré comme plus polyvalent dans la programmation fonctionnelle d'avoir une fonction qui effectue la même opération sur les données, plutôt que d'avoir une fonction qui s'applique plongeurs fonctions à un ensemble de données.Une autre manière de faire avec(sur) la préservation clés:
Vous pouvez utiliser carte méthode à partir de ce tableau de la bibliothèque pour obtenir exactement ce que vous voulez aussi facilement que:
aussi, il conserve les clés et renvoie nouveau tableau, pour ne pas mentionner quelques-uns des différents modes en fonction de vos besoins.