map - ejemplos - ¿Cómo puedo convertir un LazySeq de caracteres en una cadena en Clojure?
clojure ejemplos (3)
Como un caso especial, si el tipo subyacente de la secuencia en cuestión es clojure.lang.StringSeq
también puede hacer:
(.s (my-seq))
que es extremadamente eficiente ya que solo está sacando el campo CharSequence final público de la clase clojure StringSeq.
Ejemplo:
(type (seq "foo"))
=> clojure.lang.StringSeq
(.s (seq "foo"))
=> "foo"
(type (.s (seq "foo")))
=> java.lang.String
un ejemplo de las implicaciones de tiempo (y tenga en cuenta la diferencia al usar una sugerencia de tipo):
(time
(let [q (seq "xxxxxxxxxxxxxxxxxxxx")]
(dotimes [_ 1000000]
(apply str q))))
"Elapsed time: 620.943971 msecs"
=> nil
(time
(let [q (seq "xxxxxxxxxxxxxxxxxxxx")]
(dotimes [_ 1000000]
(.s q))))
"Elapsed time: 1232.119319 msecs"
=> nil
(time
(let [^StringSeq q (seq "xxxxxxxxxxxxxxxxxxxx")]
(dotimes [_ 1000000]
(.s q))))
"Elapsed time: 3.339613 msecs"
=> nil
Digamos que tengo un LazySeq de java.lang.Character como
(/b / /! // /b / /% /1 /9 // /. /i /% /$ /i /space /^@)
¿Cómo puedo convertir esto a una Cadena? He intentado lo obvio
(String. my-char-seq)
pero tira
java.lang.IllegalArgumentException: No matching ctor found for class java.lang.String (NO_SOURCE_FILE:0)
[Thrown class clojure.lang.Compiler$CompilerException]
Creo que porque el constructor de String espera un primitivo char [] en lugar de un LazySeq . Entonces intenté algo como
(String. (into-array my-char-seq))
pero arroja la misma excepción. El problema ahora es que into-array está devolviendo java.lang.Character [] en lugar de un primitivo char [] . Esto es frustrante, porque en realidad genero mi secuencia de caracteres como esta
(map #(char (Integer. %)) seq-of-ascii-ints)
Básicamente tengo un seq de entradas que representan caracteres ASCII; 65 = A, etc. Puede ver que utilizo explícitamente la función de coerción de tipo primitivo (char x) .
Lo que esto significa es que mi función de mapa está devolviendo un carácter primitivo, pero la función del mapa Clojure en general está devolviendo el objeto java.lang.Character .
Esto funciona:
(apply str my-char-seq)
Básicamente, str llama a String () en cada uno de sus argumentos y luego los concatena. Aquí estamos usando aplicar para pasar los caracteres en la secuencia como args a str .
Otra forma es usar clojure.string/join
, de la siguiente manera:
(require ''[clojure.string :as str] )
(assert (= (vec "abcd") [/a /b /c /d] ))
(assert (= (str/join (vec "abcd")) "abcd" ))
(assert (= (apply str (vec "abcd")) "abcd" ))
Hay una forma alternativa de clojure.string/join
que acepta un separador. Ver:
http://clojuredocs.org/clojure_core/clojure.string/join
Para problemas más complicados, también puede buscar strcat
desde la biblioteca de Tupelo :
(require ''[tupelo.core :as t] )
(prn (t/strcat "I " [ /h /a nil /v [/e /space (byte-array [97])
[ nil 32 "complicated" (Math/pow 2 5) ''( "str" nil "ing") ]]] ))
;=> "I have a complicated string"