2009-11-06 51 views
46

Hãy nói rằng tôi có một LazySeq của java.lang.Character nhưLàm cách nào để chuyển đổi một ký tự LazySeq thành một chuỗi trong Clojure?

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

Làm thế nào tôi có thể chuyển đổi này vào một String? Tôi đã cố gắng rõ ràng

(String. my-char-seq) 

nhưng nó ném

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

Tôi nghĩ rằng bởi vì các nhà xây dựng chuỗi hy vọng một char nguyên thủy [] thay vì một LazySeq. Vì vậy, sau đó tôi đã thử một cái gì đó như

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

nhưng nó cũng ném cùng một ngoại lệ. Vấn đề bây giờ là thành mảng đang trả về một java.lang.Character [] thay vì một số nguyên thủy char []. Điều này thật khó chịu, bởi vì tôi thực sự tạo chuỗi ký tự như thế này

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

Về cơ bản tôi có một số nguyên nhân đại diện cho các ký tự ASCII; 65 = A, v.v. Bạn có thể thấy rõ ràng tôi sử dụng hàm cưỡng chế kiểu nguyên thủy (char x).

Điều này có nghĩa là đồ chức năng của tôi đang trở lại một nguyên thủy char nhưng Clojure đồ chức năng tổng thể được trả lại java.lang.Character đối tượng.

Trả lời

97

này hoạt động:

(apply str my-char-seq) 

Về cơ bản, str gọi toString() trên mỗi người trong số args của nó và sau đó concatenates chúng. Ở đây chúng tôi đang sử dụng áp dụng để chuyển các ký tự theo thứ tự như args đến str.

10

Một cách khác là sử dụng clojure.string/join, như sau:

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

Có một dạng thay thế của clojure.string/join mà chấp nhận một tách.Xem:

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

Đối với các vấn đề phức tạp hơn, bạn cũng có thể muốn lookat strcatfrom the Tupelo library:

(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

Là một trường hợp đặc biệt, nếu loại cơ bản của chuỗi trong câu hỏi là clojure.lang.StringSeq bạn có thể cũng làm:

(.s (my-seq)) 

cực kỳ hiệu quả vì nó chỉ là kéo o ut lĩnh vực CharSequence cuối cùng công khai từ lớp StringSeq clojure.

Ví dụ:

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

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

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

một ví dụ về những tác động thời gian (và lưu ý sự khác biệt khi sử dụng một loại gợi ý):

(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 
Các vấn đề liên quan