Existe-t-il un moyen de faire quelque chose comme ça:
$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
etarray_values
passer directement$test_array
variable?
La sortie souhaitée est:
array(2) {
[0]=>
string(27) "first_key loves first_value"
[1]=>
string(29) "second_key loves second_value"
}
php
functional-programming
José Tomás Tocino
la source
la source
Réponses:
Pas avec array_map, car il ne gère pas les clés.
array_walk fait:
Cependant, cela change le tableau donné en paramètre, donc ce n'est pas exactement une programmation fonctionnelle (comme vous avez la question étiquetée comme ça). De plus, comme indiqué dans le commentaire, cela ne changera que les valeurs du tableau, donc les clés ne seront pas celles que vous avez spécifiées dans la question.
Vous pouvez écrire une fonction qui corrige les points au-dessus de vous si vous le souhaitez, comme ceci:
la source
$a = "$b loves $a"
, faire correspondre la sortie souhaitée de l'OP.array_walk()
cela ne renvoie pas le tableau résultant, mais un booléen à la place.C'est probablement le plus court et le plus facile à raisonner sur:
la source
array_keys()
. Cela semble cependant une exigence stupide.Voici ma solution très simple, compatible avec PHP 5.5:
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_map
produit donc un tableau de tableaux. Celui-ci est ensuite reconverti en un tableau à une dimension pararray_column
.Usage
Production
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:
Qui produit la même sortie, donnée
$func
et$ordinals
sont 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_assoc
pour 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:
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.Si vous utilisez PHP 5.3 à 5.5, ce qui suit est équivalent. Il utilise
array_reduce
et l'+
opérateur de tableau binaire pour convertir le tableau bidimensionnel résultant en un tableau unidimensionnel tout en préservant les clés:Usage
Ces deux variantes seraient utilisées ainsi:
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:
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: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_keys
est appelé une fonction d'ordre supérieur, ce qui pourrait être suffisant.la source
array_merge
pararray_replace
pour conserver les clés qui seraient des entiers.Avec PHP5.3 ou version ultérieure:
la source
C'est ainsi que j'ai implémenté cela dans mon projet.
la source
Regardez ici! Il y a une solution triviale!
Comme indiqué dans la question, a
array_map
déjà exactement les fonctionnalités requises . Les autres réponses ici compliquent sérieusement les choses:array_walk
n'est pas fonctionnelle.Usage
Exactement ce que vous attendez de votre exemple:
la source
qrrqy_keys()
ne doit pas être utilisée pour # raisonsPar «boucle manuelle», j'entendais écrire une fonction personnalisée qui utilise
foreach
. Cela retourne un nouveau tableau comme learray_map
fait parce que la portée de la fonction$array
est une copie, pas une référence:Votre technique utilisant
array_map
avecarray_keys
bien que semble en fait plus simple et est plus puissante car vous pouvez utilisernull
comme rappel pour renvoyer les paires clé-valeur:la source
unset( $value )
car il existe toujours dans la portée définie.Sur la base de la réponse d'eis , voici ce que j'ai finalement fait pour éviter de salir le tableau d'origine:
la source
array_walk
car vous ne le faites pas référence dans la fermeture.J'ai fait cette fonction, basée sur la réponse d'eis :
Exemple:
Production:
Bien sûr, vous pouvez utiliser
array_values
pour retourner exactement ce que OP souhaite.la source
$arr
de type tableau, cependant si vous tapez-hint vos arguments commecallable
etarray
vous pouvez à la place déposer la vérificationis_callable
. Ensuite, vous effectuez une affectation à $ value qui est ensuite inutilisée. Vous devez simplement ignorer la valeur de retour. Troisièmement, il serait préférable de lever une exception dans le rappel que de retourner false. Vous devez alors toujours renvoyer une valeur valide ou toujours lancer.La bibliothèque YaLinqo * est bien adaptée à ce type de tâche. C'est un port de LINQ de .NET qui prend entièrement en charge les valeurs et les clés dans tous les rappels et ressemble à SQL. Par exemple:
ou juste:
Voici
'"$k loves $v"'
un raccourci pour la syntaxe de fermeture complète que cette bibliothèque prend en charge.toArray()
à la fin est facultative. La chaîne de méthodes renvoie un itérateur, donc si le résultat doit simplement être itéré au cours de l'utilisationforeach
, l'toArray
appel peut être supprimé.* développé par mes soins
la source
Je ferais quelque chose comme ça:
Résultats:
la source
J'ajouterai encore une autre solution au problème en utilisant la version 5.6 ou ultérieure. Je ne sais pas si c'est plus efficace que les excellentes solutions (probablement pas), mais pour moi c'est juste plus simple à lire:
En utilisant
strval()
comme exemple de fonction dans learray_map
, cela générera:J'espère que je ne suis pas le seul à trouver cela assez simple à comprendre.
array_combine
crée unkey => value
tableau à partir d'un tableau de clés et d'un tableau de valeurs, le reste est assez explicite.la source
Vous pouvez utiliser la méthode map de cette bibliothèque de tableaux pour obtenir exactement ce que vous voulez aussi facilement que:
il conserve également les clés et renvoie un nouveau tableau, sans parler de quelques modes différents pour répondre à vos besoins.
la source
La source
la source
J'aime toujours la variante javascript de la carte du tableau. La version la plus simple serait:
Alors maintenant, vous pouvez simplement lui passer une fonction de rappel comment construire les valeurs.
la source
h(g(f($data)))
s'appliquef
, puisg
, puish
à votre Les 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 des données de plongeurs, que d'avoir une fonction qui applique des fonctions de plongeurs à un ensemble de données fixe.Une autre façon de le faire avec (out) la préservation des clés:
la source
Je vois qu'il manque la réponse évidente:
Fonctionne exactement comme array_map. Presque.
En fait, ce n'est pas pur
map
comme vous le savez dans d'autres langues. Php est très bizarre, il nécessite donc des fonctions utilisateur très étranges, car nous ne voulons pas casser notre cassé avec précisionworse is better
approche .Vraiment, ce n'est pas
map
du tout le cas. Pourtant, c'est toujours très utile.La première différence évidente avec array_map, est que le rappel prend les sorties de
each()
chaque tableau d'entrée au lieu de la valeur seule. Vous pouvez toujours parcourir plusieurs tableaux à la fois.La deuxième différence est la façon dont la clé est gérée après son retour de rappel; la valeur de retour de la fonction de rappel doit être
array('new_key', 'new_value')
. Les clés peuvent et seront modifiées, les mêmes clés peuvent même entraîner l'écrasement de la valeur précédente, si la même clé a été retournée. Ce n'est pas unmap
comportement courant , mais il vous permet de réécrire des clés.La troisième chose étrange est que si vous omettez la
key
valeur de retour (soit pararray(1 => 'value')
ouarray(null, 'value')
), une nouvelle clé va être affectée, comme si elle$array[] = $value
était utilisée. Ce n'est pasmap
un comportement commun non plus, mais il est parfois utile, je suppose.Quatrième chose étrange: si la fonction de rappel ne renvoie pas de valeur, ou renvoie
null
, l'ensemble des clés et valeurs actuelles est omis de la sortie, il est simplement ignoré. Cette fonctionnalité est totalementmap
inutilisable, mais elle ferait de cette fonction un excellent doublon pourarray_filter_assoc
, s'il y avait une telle fonction.Si vous omettez le deuxième élément (
1 => ...
) (la partie valeur ) dans le retour du rappel,null
est utilisé à la place de la valeur réelle.Tous les autres éléments à l'exception de ceux avec des clés
0
et1
dans le retour de rappel sont ignorés.Et enfin, si lambda retourne une valeur autre que
null
ou tableau, il est traité comme si la clé et la valeur étaient omises, donc:null
est utilisé comme sa valeurREMARQUE:
contrairement à dans
array_map
, tous les paramètres non tableau passés àarray_map_assoc
, à l'exception du premier paramètre de rappel, sont castés en silence dans les tableaux.EXEMPLES:
// TODO: examples, anyone?
la source