2009-11-06 6 views
46

Lassen Sie uns sagen, ich habe eine LazySeq von java.lang.Character wieWie kann ich ein LazySeq Zeichen in Clojure in einen String konvertieren?

(\b \ \! \/ \b \ \% \1 \9 \/ \. \i \% \$ \i \space \^@) 

Wie kann ich dies in einen String konvertieren? Ich habe versucht, die offensichtlichen

(String. my-char-seq) 

aber es wirft

java.lang.IllegalArgumentException: No matching ctor found for class java.lang.String (NO_SOURCE_FILE:0) 
[Thrown class clojure.lang.Compiler$CompilerException] 

Ich denke, da das String-Konstruktor einen primitiven char erwartet [] anstelle einem LazySeq. Also habe ich etwas wie

(String. (into-array my-char-seq)) 

versucht, aber es löst die gleiche Ausnahme aus. Das Problem besteht nun darin, dass in-array einen java.lang.Character [] anstelle eines primitiven char [] zurückgibt. Das ist frustrierend, weil ich generieren tatsächlich meine Zeichenfolge wie diese

(map #(char (Integer. %)) seq-of-ascii-ints) 

Im Grunde habe ich eine seq von Ints ASCII-Zeichen darstellen; 65 = A, etc. Sie können sehen, ich verwende explizit die primitive Art Zwangsfunktion (char x).

Was dies bedeutet, ist, dass meine Karte Funktion einen primitiven char kehrt aber die Clojure Karte Funktion Gesamt kehrt das java.lang.Character Objekt.

Antwort

97

Dies funktioniert:

(apply str my-char-seq) 

Grundsätzlich str toString() auf jeder seiner args nennt und verkettet sie dann. Hier verwenden wir anwenden, um die Zeichen in der Sequenz als Args an str zu übergeben.

10

Ein anderer Weg ist clojure.string/join zu verwenden, wie folgt:

(require '[clojure.string :as str]) 
(assert (= (vec "abcd")    [\a \b \c \d])) 
(assert (= (str/join (vec "abcd")) "abcd")) 
(assert (= (apply str (vec "abcd")) "abcd")) 

Es ist eine alternative Form von clojure.string/join die einen Separator übernimmt.Siehe:

http://clojuredocs.org/clojure_core/clojure.string/join

Für kompliziertere Probleme, können Sie auch from the Tupelo library lookat strcat wünschen:

(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" 
3

Als Sonderfall, wenn die zugrunde liegende Art der betreffenden Sequenz ist clojure.lang.StringSeq möglich auch tun:

die extrem performant ist, wie es gerade o zieht ut das öffentliche letzte CharSequence-Feld aus der clojure StringSeq-Klasse.

Beispiel:

(type (seq "foo")) 
=> clojure.lang.StringSeq 

(.s (seq "foo")) 
=> "foo" 

(type (.s (seq "foo"))) 
=> java.lang.String 

ein Beispiel der Zeit Auswirkungen (und den Unterschied zu beachten, wenn ein Typ Hinweis verwenden):

(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 
Verwandte Themen