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 . La mettre en œuvre n'est pas difficile, mais je voulais m'assurer ne manquait aucune fonction dans Core ou Contrib.
Il y a un espace de noms Zip dans Core, mais il est décrit comme donnant accès à la technique fonctionnelle Zipper, qui ne semble pas être ce que je recherche.
Existe-t-il une fonction équivalente pour combiner 2 listes ou plus, de cette manière, dans Core?
S'il n'y en a pas, est-ce parce qu'il existe une approche idiomatique qui rend la fonction inutile?
(map vector '(1 2 3) '(4 5 6))
fait ce que vous voulez:
=> ([1 4] [2 5] [3 6])
Haskell a besoin d'une collection de zipWith
(zipWith3
, zipWith4
, ...), car elles doivent toutes être de type type; en particulier, le nombre de listes d'entrées qu'ils acceptent doit être fixé. (Les Zip
, Zip2
, Zip3
, ... peut être considérée comme une spécialisation de la famille zipWith
pour le cas d'utilisation courant du tupling).
En revanche, Clojure et d'autres Lisps ont un bon support pour les fonctions d'arité variable; map
est l'un d'entre eux et peut être utilisé pour le "tupling" d'une manière similaire à celle de Haskell
zipWith (\x y -> (x, y))
La façon idiomatique de construire un "Tuple" dans Clojure est de construire un vecteur court, comme indiqué ci-dessus.
(Juste pour être complet, notez que Haskell avec certaines extensions de base autorise les fonctions d'arité variables; cependant, leur utilisation nécessite une bonne compréhension du langage, 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.)
(partition 2 (interleave '(1 2 3) '(4 5 6)))
=> ((1 4) (2 5) (3 6))
ou plus généralement
(defn Zip [& colls]
(partition (count colls) (apply interleave colls)))
(Zip '( 1 2 3) '(4 5 6)) ;=> ((1 4) (2 5) (3 6))
(Zip '( 1 2 3) '(4 5 6) '(2 4 8)) ;=> ((1 4 2) (2 5 4) (3 6 8))
(map vector [1 2 3] [4 5 6])
pour vous donner exactement ce que vous vouliez, mapper list
sur 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 séquences à partir d'eux puis mappe les séquences afin que toute entrée seq'able fonctionne correctement.
(map list '(1 2 3) '(4 5 6))
(map list [1 2 3] '(4 5 6))
(map hash-map '(1 2 3) '(4 5 6))
(map hash-set '(1 2 3) '(4 5 6))
La manière intégrée serait simplement la fonction "entrelacement":
(interleave [1 2 3 4] [5 6 7 8]) => [1 5 2 6 3 7 4 8]