我怎样才能将字符LazySeq转换为Clojure中的string?
比方说,我有一个像 java.lang.Character一样的LazySeq
(\b \ \! \/ \b \ \% \1 \9 \/ \. \i \% \$ \i \space \^@)
我怎样才能将其转换为string? 我已经尝试了明显的
(String. my-char-seq)
但它抛出
java.lang.IllegalArgumentException: No matching ctor found for class java.lang.String (NO_SOURCE_FILE:0) [Thrown class clojure.lang.Compiler$CompilerException]
我想是因为String构造函数需要一个原始的char []而不是LazySeq 。 所以然后我尝试了类似的东西
(String. (into-array my-char-seq))
但它会抛出同样的exception。 现在的问题是, 数组是返回一个java.lang.Character []而不是一个原始的字符[] 。 这是令人沮丧的,因为我实际上是这样产生我的字符序列
(map #(char (Integer. %)) seq-of-ascii-ints)
基本上我有一个代表ASCII字符的整数, 65 = A等你可以看到我明确地使用了原始types强制函数(char x) 。
这意味着我的map函数正在返回一个原始字符,但是Clojure map函数总体上返回了java.lang.Character对象。
这工作:
(apply str my-char-seq)
基本上, str在每个参数上调用toString(),然后连接它们。 这里我们使用apply将序列中的字符作为parameter passing给str 。
另一种方法是使用clojure.string/join
,如下所示:
(require '[clojure.string :as str] ) (assert (= (vec "abcd") [\a \b \c \d] )) (assert (= (str/join (vec "abcd")) "abcd" )) (assert (= (apply str (vec "abcd")) "abcd" ))
clojure.string/join
有一个替代forms,它接受一个分隔符。 看到:
http://clojuredocs.org/clojure_core/clojure.string/join
对于更复杂的问题,你也可以从图珀洛图书馆看看strcat
:
(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"
作为一个特例,如果序列的基础types是clojure.lang.StringSeq
你也可以这样做:
(.s (my-seq))
这是非常高性能的,因为它只是从clojure StringSeq类中提取公共的最终CharSequence字段。
例:
(type (seq "foo")) => clojure.lang.StringSeq (.s (seq "foo")) => "foo" (type (.s (seq "foo"))) => java.lang.String
时间影响的一个例子(并注意使用types提示时的差异):
(time (let [q (seq "xxxxxxxxxxxxxxxxxxxx")] (dotimes [_ 1000000] (apply str q)))) "Elapsed time: 620.943971 msecs" => nil (time (let [q (seq "xxxxxxxxxxxxxxxxxxxx")] (dotimes [_ 1000000] (.sq)))) "Elapsed time: 1232.119319 msecs" => nil (time (let [^StringSeq q (seq "xxxxxxxxxxxxxxxxxxxx")] (dotimes [_ 1000000] (.sq)))) "Elapsed time: 3.339613 msecs" => nil