online - ¿En Clojure hay una forma fácil de convertir entre tipos de lista?
clojure web framework (6)
A menudo me encuentro usando una lista perezosa cuando quiero un vector, y viceversa. Además, a veces tengo un vector de mapas, cuando realmente quería un conjunto de mapas. ¿Hay alguna función auxiliar que me ayude a convertir estos tipos?
No es necesario convertir un vector en una lista. Clojure tratará un vector como trataría una lista, como una secuencia, cuando se requiera una secuencia. Por ejemplo,
user=> (cons 0 [1 2 3])
(0 1 2 3)
Si necesita asegurarse de que el vector se trata como una secuencia, envuélvalo en la secuencia:
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 tienes un vector de mapas y quieres un conjunto de mapas, no importa que el vector tenga mapas. Simplemente convierte el vector a un conjunto como de costumbre:
user=> (set [{:a 1, :b 2} {"three" 3, "four" 4}])
#{{:a 1, :b 2} {"four" 4, "three" 3}}
Para convertir un vector en una lista también puede usarlo, como este:
=> (for [i [1 2 3 4]] i)
(1 2 3 4)
Cuando no desee manipular los datos, simplemente use seq
en el vector:
=> (seq [1 2 3])
(1 2 3)
Para vectores está la función vec
user=> (vec ''(1 2 3))
[1 2 3]
Para las secuencias perezosas existe la función lazy-seq
user=> (lazy-seq [1 2 3])
(1 2 3)
Para convertir en conjuntos, existe la función set
user=> (set [{:a :b, :c :d} {:a :b} {:a :b}])
#{{:a :b} {:a :b, :c :d}}
Una respuesta más para convertir de una lista a un mapa (en aras de la exhaustividad), desde here :
(apply hash-map ''(1 2 3 4))
;=>{1 2, 3 4}
vec
, set
y into
general son tus amigos para "convertir" fácilmente a otro tipo de colección.
¿Cómo quieres transformar un vector de mapas en un mapa de mapas? Necesita una clave, ¿puede proporcionar el uso con la entrada de muestra / salida esperada?
No olvidemos que la opción de confianza le permite tomar cualquier elemento (lista, vector, mapa, conjunto, mapa ordenado) y un contenedor vacío que desee llenar, y lo coloca into
él.
(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
es un wrapper alrededor de conj
, que es la abstracción base para insertar apropiadamente nuevas entradas en una colección en función del tipo de la colección. El principio que hace que esto fluya tan bien es que Clojure se basa en abstracciones compostables , en este caso into
parte superior de la conj
encima de la colección y las seq
.
Los ejemplos anteriores seguirían componiendo bien si el destinatario se estaba transfiriendo en tiempo de ejecución: porque las abstracciones subyacentes ( seq
y conj
) se implementan para todas las colecciones (y muchas de las colecciones de Java también), por lo que las abstracciones superiores no necesitan preocuparse por muchos casos de esquina relacionados con datos especiales.