Dans Clojure, je veux combiner deux listes pour donner une liste de paires,
> (zip '(1 2 3) '(4 5 6))
((1 4) (2 5) (3 6))
Dans Haskell ou Ruby, la fonction est appelée zip . L'implémenter n'est pas difficile, mais je voulais m'assurer de ne pas manquer une fonction dans Core ou Contrib.
Il existe un espace de noms zip dans Core, mais il est décrit comme donnant accès à la technique fonctionnelle Zipper, ce qui ne semble pas être ce que je recherche.
Existe-t-il une fonction équivalente pour combiner 2 ou plusieurs listes, de cette manière, dans Core?
S'il n'y en a pas, est-ce parce qu'il y a une approche idiomatique qui rend la fonction inutile?
zip
fonction dans la bibliothèque Tupelo: cloojure.github.io/doc/tupelo/tupelo.core.html#var-zipRéponses:
fait ce que vous voulez:
Haskell a besoin d'une collection de fonctions
zipWith
(zipWith3
,,zipWith4
...), car elles doivent toutes être d'un type spécifique ; en particulier, le nombre de listes d'entrée qu'ils acceptent doit être fixé. (Lezip
,zip2
,zip3
, ... la famille peut être considérée comme une spécialisation de lazipWith
famille pour le cas d'utilisation commune de Tupling).En revanche, Clojure et d'autres Lisps supportent bien les fonctions d'arité variable;
map
est l'un d'entre eux et peut être utilisé pour "tupling" d'une manière similaire à celle de HaskellLa manière idiomatique de construire un "tuple" dans Clojure est de construire un vecteur court, comme illustré ci-dessus.
(Juste pour être complet, notez que Haskell avec certaines extensions de base autorise les fonctions d'arité variable; leur utilisation nécessite une bonne compréhension du langage, cependant, et le vanilla Haskell 98 ne les prend probablement pas en charge du tout, donc les fonctions d'arité fixes sont préférables pour la bibliothèque standard.)
la source
zip
lorsque les collections ne sont pas de la même longueur. Ruby continuera le traitement et fournira desnil
s pour la collection plus courte, tandis que Clojure arrêtera le traitement une fois que l'une des collections sera épuisée.zip
se comporte comme Clojuremap
à cet égard.ou plus généralement
la source
la source
pour vous donner exactement ce que vous vouliez, le mappage
list
entre les deux listes vous donnera une liste de listes comme dans votre exemple. Je pense que de nombreux Clojuriens auraient tendance à utiliser des vecteurs pour cela même si cela fonctionnera avec n'importe quoi. et les entrées n'ont pas besoin d'être du même type. map crée des seqs à partir d'eux, puis mappe les seqs afin que toute entrée séq'able fonctionne correctement.la source
La manière intégrée serait simplement la fonction 'entrelacer':
la source
(partition 2 (interleave [1 2 3 4][5 6 7 8]))
Il existe une fonction appelée zipmap, qui peut avoir un effet similaire, (zipmap
(1 2 3)
(4 5 6)) La sortie est comme des fllows: {3 6, 2 5, 1 4}la source
# (apply map list%) transpose une matrice comme la fonction zip * de Python. En tant que définition de macro:
user => (defmacro py-zip [lst] `(appliquer la liste des cartes ~ lst))
# 'utilisateur / py-zip
utilisateur => (py-zip '((1 2 3 4) (9 9 9 9) (5 6 7 8)))
((1 9 5) (2 9 6) (3 9 7) (4 9 8))
utilisateur => (py-zip '((1 9 5) (2 9 6) (3 9 7) (4 9 8)))
((1 2 3 4) (9 9 9 9) (5 6 7 8))
la source