web-dev-qa-db-fra.com

Dans Clojure, existe-t-il un moyen facile de convertir entre les types de liste?

Je me retrouve souvent à utiliser une liste paresseuse quand je veux un vecteur, et vice versa. De plus, j'ai parfois un vecteur de cartes, alors que je voulais vraiment un ensemble de cartes. Existe-t-il des fonctions d'aide pour m'aider à convertir entre ces types?

87
Zubair

N'oublions pas que l'ancien fidèle into vous permet de prendre n'importe quoi seqable (liste, vecteur, carte, ensemble, carte triée) et un conteneur vide que vous voulez remplir, et le met into il.

(into [] '(1 2 3 4)) ==> [1 2 3 4]         "have a lazy list and want a vector"
(into #{} [1 2 3 4]) ==> #{1 2 3 4}        "have a vector and want a set"
(into {} #{[1 2] [3 4]}) ==> {3 4, 1 2}    "have a set of vectors want a map"
(into #{} [{1 2} {3 4}]) ==> #{{1 2} {3 4}} "have a vector of maps want a set of maps"

into est un wrapper autour de conj, qui est l'abstraction de base pour insérer de nouvelles entrées de manière appropriée dans une collection en fonction du type de la collection. Le principe qui rend ce flux si agréable est que Clojure est construit sur abstractions composables, dans ce cas into en haut de conj en haut de collection et seq.

Les exemples ci-dessus seraient toujours bien composés si le destinataire était transmis au moment de l'exécution: car les abstractions sous-jacentes (seq et conj) sont implémentées pour toutes les collections (et de nombreuses collections Java également ), de sorte que les abstractions supérieures n'ont pas à se soucier de beaucoup de cas d'angle spéciaux liés aux données.

136
Arthur Ulfeldt

vec, set et généralement into sont vos amis pour "convertir" facilement en un autre type de collection.

Comment voulez-vous transformer un vecteur de cartes en une carte de cartes? Vous avez besoin d'une clé, pouvez-vous fournir une utilisation avec un échantillon d'entrée/sortie attendue?

31
cgrand

Pour les vecteurs, il y a la fonction vec

user=> (vec '(1 2 3))
[1 2 3]

Pour les séquences paresseuses, il y a le lazy-seq une fonction

user=> (lazy-seq [1 2 3])
(1 2 3)

Pour la conversion en ensembles, il existe la fonction set

user=> (set [{:a :b, :c :d} {:a :b} {:a :b}])
#{{:a :b} {:a :b, :c :d}}
19
cobbal

Une autre réponse pour la conversion d'une liste en une carte (par souci d'exhaustivité) - de ici :

(apply hash-map '(1 2 3 4))
;=>{1 2, 3 4}
12
hawkeye

Pour convertir un vecteur en liste, vous pouvez également utiliser for, comme ceci:

=> (for [i [1 2 3 4]] i)
(1 2 3 4)

Lorsque vous ne voulez pas manipuler les données, utilisez simplement seq sur le vecteur:

=> (seq [1 2 3])
(1 2 3)
8
Geert-Jan Hut

Il n'est pas nécessaire de convertir un vecteur en liste. Clojure traitera un vecteur comme il traiterait une liste - comme une séquence - lorsqu'une séquence est requise. Par exemple,

user=> (cons 0 [1 2 3])
(0 1 2 3)

Si vous devez vous assurer que le vecteur est traité comme une séquence, enveloppez-le dans seq:

user=> (conj [1 2 3] 0) ; treated as a vector
[1 2 3 0]

user=> (conj (seq [1 2 3]) 0) ; treated as a sequence
(0 1 2 3)

Si vous avez un vecteur de cartes et que vous voulez un ensemble de cartes, peu importe que le vecteur contienne des cartes. Vous venez de convertir le vecteur en un ensemble comme d'habitude:

user=> (set [{:a 1, :b 2} {"three" 3, "four" 4}])
#{{:a 1, :b 2} {"four" 4, "three" 3}}
6
Thumbnail