web-dev-qa-db-fra.com

Existe-t-il un équivalent pour la fonction Zip dans Clojure Core ou Contrib?

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?

117
John Kane
(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.)

204
Michał Marczyk
(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))
16
Lambder
(map vector [1 2 3] [4 5 6])
12
danlei

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))
10
Arthur Ulfeldt

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]
3
lsh