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 entre estos tipos?
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 entre estos tipos?
Respuestas:
No olvidemos que trusty old le into
permite tomar cualquier cosa que seq
pueda (lista, vector, mapa, conjunto, mapa ordenado) y un contenedor vacío que desee llenar, y lo coloca into
.
(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 envoltorio conj
, que es la abstracción básica para insertar nuevas entradas de manera adecuada en una colección según el tipo de colección. El principio que hace que esto fluya tan bien es que Clojure se basa en abstracciones componibles , en este caso into
sobre la conj
colección y seq
.
Los ejemplos anteriores aún se compondrían bien si el destinatario se pasara 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 más altas no necesitan preocuparse. sobre muchos casos especiales relacionados con los datos.
into
usos conj
, el hacer (into '() some-seq)
producirán una lista que es la inversa de some-seq, porque se conj
convierte en listas.
into
utiliza transitorios (para la mayoría de los tipos de secuencia) para obtener mejores características de rendimiento que la mayoría de los otros medios de conversión.
vec
set
y , en general, into
son tus amigos para "convertir" fácilmente a otro tipo de colección.
¿Cómo quiere transformar un vector de mapas en un mapa de mapas? Necesita una clave, ¿puede proporcionar uso con entrada de muestra / salida esperada?
Para los vectores existe la vec
función
user=> (vec '(1 2 3))
[1 2 3]
Para las secuencias perezosas existe la lazy-seq
función
user=> (lazy-seq [1 2 3])
(1 2 3)
Para convertir en conjuntos, existe la set
función
user=> (set [{:a :b, :c :d} {:a :b} {:a :b}])
#{{:a :b} {:a :b, :c :d}}
lazy-seq
lugar de seq
simplemente agrega una indirección inútil. Si realmente desea devolver algo que no sea nulo, incluso antes de que exista una colección vacía sequence
. lazy-seq
es algo así como una construcción de bajo nivel.
Una respuesta más para convertir de una lista a un mapa (en aras de la integridad), desde aquí :
(apply hash-map '(1 2 3 4))
;=>{1 2, 3 4}
Para convertir un vector en una lista también puede usar for
, así:
=> (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)
for
hacerlo, simplemente podría hacerlo(map identity [1 2 3 4])
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 esté tratando como una secuencia, envuélvalo en 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 tiene un vector de mapas y desea un conjunto de mapas, no importa que el vector contenga mapas. Simplemente convierta el vector en un conjunto como de costumbre:
user=> (set [{:a 1, :b 2} {"three" 3, "four" 4}])
#{{:a 1, :b 2} {"four" 4, "three" 3}}