web-dev-qa-db-fra.com

Comment puis-je fusionner deux séquences en clojure?

Quelle est une manière idiomatique de fusionner (ou de récupérer l'union de) deux listes (ou séquences) dans Clojure?

(merge l1 l2)

ne semble pas être la solution:

a=> (merge '(1 2 3) '(2 3 4))
((2 3 4) 1 2 3)
29
user1639206

Je pense que la solution d'Andih fonctionne très bien. Voici une alternative car bon pourquoi pas. Il utilise concat et distinct :

user> (distinct (concat '(1 2 3) '(2 3 4)))
=> (1 2 3 4)
28
Omri Bernstein

Une façon d'obtenir l'union de deux listes est d'utiliser union

Clojure> (into #{} (clojure.set/union '(1,2,3) '(3,4,5)))
#{1 2 3 4 5}

ou si vous voulez obtenir une liste

(into '() (into #{} (clojure.set/union '(1,2,3) '(3,4,5))))
(5 4 3 2 1)
14
andih

Si vous voulez en fait des données (ensembles) non triées distinctes, vous devez utiliser la structure de données d'ensemble de Clojure au lieu de vecteurs ou de listes. Et comme l'a suggéré andih indirectement, il existe une bibliothèque de base pour les opérations d'ensemble: http://clojure.github.com/clojure/clojure.set-api.html

(require '[clojure.set :refer [union]])

(union #{1 2 3} #{3 4 5})
=> #{1 2 3 4 5}

Si les ensembles ne sont pas ce que vous voulez pour quelque raison que ce soit, alors lisez la suite. Soyez prudent avec concat lorsque vous avez une quantité importante de données dans vos séquences, et envisagez d'utiliser into qui est beaucoup mieux optimisé comme algorithme de fusion vectorielle. Je ne sais pas pourquoi concat n'est pas implémenté en utilisant dans (ou mieux encore - pourquoi existe-t-il même? BTW alors que dans est beaucoup plus rapide que concat, il est encore beaucoup plus lent que les arbres RRB conj. et Scala, résoudra ce problème, mais ne sont pas encore implémentés pour Clojure).

Pour reformuler la solution non définie d'Omri en termes de "en":

(distinct (into [1 2 3] [3 4 5]))
=> (1 2 3 4 5)
14
rplevy

Si cela ne vous dérange pas, vous pouvez essayer concat :

(concat '(1 2 3 ) '(4 5 6 1) '(2 3)) 
;;==> (1 2 3 4 5 6 1 2 3) 
7
Kevin Zhu

Une option est aplatir :

(def colls '((1 2 3) (2 3 4)))
(flatten colls) ;; => (1 2 3 2 3 4)
(distinct (flatten colls)) ;; => (1 2 3 4)

Une chose à savoir est qu'elle aplatira les collections profondément imbriquées:

(flatten [[1 2 [3 4 5]] [1 [2 [3 4]]]]) ;; => (1 2 3 4 5 1 2 3 4)

Mais fonctionne bien pour les cartes:

(flatten [[{} {} {}] [{} {} {}]]) ;; => ({} {} {} {} {} {})
2
Kris