2011-09-19 47 views
17

有沒有更好的方式在Clojure中做到這一點?反轉一個字符串(簡單問題)

daniel=> (reverse "Hello") 
(\o \l \l \e \H) 

daniel=> (apply str (vec (reverse "Hello"))) 
"olleH" 

你有你要反向字符串返回到其原來的形式,每次做apply $ str $ vec位?

回答

24

你最好使用clojure.string/reverse

user=> (require '[clojure.string :as s]) 
nil 
user=> (s/reverse "Hello") 
"olleH" 

UPDATE:爲好奇,這裏遵循clojure.string/reverse源代碼片段都Clojure的(V1.4)和ClojureScript

; clojure: 
(defn ^String reverse 
    "Returns s with its characters reversed." 
    {:added "1.2"} 
    [^CharSequence s] 
    (.toString (.reverse (StringBuilder. s)))) 

; clojurescript 
(defn reverse 
    "Returns s with its characters reversed." 
    [s] 
    (.. s (split "") (reverse) (join ""))) 
+0

啊有道理,謝謝。在Haskell宇宙中,我仍然有點過於根深蒂固,因爲字符串只是鏈表 – djhworld

10

像反向一樣,適用於任何seqable類型,而不僅僅是向量,所以

(申請str(反向「你好」))

有點短。儘管clojure.string/reverse應該更有效率。

18

好吧,所以很容易將自己的功能應用於內部,或者使用專用版本的反轉效果更好(但僅限於)字符串。這裏要考慮的主要問題是str函數的參數(參數的數量和類型),以及反轉對集合的作用。

(doc reverse) 

clojure.core/reverse 
([coll]) 
Returns a seq of the items in coll in reverse order. Not lazy. 

這意味着反轉不僅適用於字符串,而且適用於所有其他集合。然而,由於逆需要一個集合作爲參數,它把一個字符串的字符

(reverse "Hello") 

的集合,並返回一個以及

(\o \l \l \e \H) 

現在,如果我們只是替換功能的集合,可以當場的區別:

(str '(\o \l \l \e \H)) 
"(\\o \\l \\l \\e \\H)" 

(str \o \l \l \e \H) 
"olleH" 

兩者之間的最大區別是參數的數量。在第一個示例中,str採用一個參數,即5個字符的集合。在第二個str中,有5個參數:5個字符。

str函數期望什麼?

(doc str) 
------------------------- 
clojure.core/str 
([] [x] [x & ys]) 
    With no args, returns the empty string. With one arg x, returns 
    x.toString(). (str nil) returns the empty string. With more than 
    one arg, returns the concatenation of the str values of the args. 

所以,當你給一個參數(一個集合)時,所有的str返回值都是集合的toString。 但是爲了得到您想要的結果,您需要將5個字符作爲單獨的參數提供給str,而不是集合本身。應用是用於'進入'收藏並使之發生的功能。

(apply str '(\o \l \l \e \H)) 
"olleH" 

功能可處理多個獨立的參數經常出現在Clojure的,所以這是很好實現時,爲什麼你需要使用申請。另一方面要意識到的是,爲什麼str函數的作者使它接受多個參數而不是集合?通常,有一個很好的理由。 str函數的流行用例是什麼?不是連續確定單獨字符的集合,而是連接值,字符串和函數結果。

(let [a 1 b 2] 
    (str a "+" b "=" (+ a b))) 
"1+2=3" 

如果我們有一個接受單個集合作爲參數的str,該怎麼辦?

(defn str2 
    [seq] 
    (apply str seq) 
) 

(str2 (reverse "Hello")) 
"olleH" 

很酷,它的工作原理!但現在:

(let [a 1 b 2] 
    (str2 '(a "+" b "=" (+ a b))) 
) 
"a+b=(+ a b)" 

嗯,現在該怎麼解決? :)

在這種情況下,使str接受在執行str函數之前評估的多個參數給str提供了最簡單的語法。無論何時需要在集合上使用str,應用都是將集合轉換爲單獨參數的簡單方法。

創建一個接受集合並讓它評估每個零件的str將花費更多的精力,僅在不常見的用例中提供幫助,導致更復雜的代碼或語法或限制其適用性。所以可能有更好的方法來反轉字符串,但反轉,應用和str是他們所做的最好的方法。

+0

感謝您的詳細回覆,這對於瞭解和解釋(非常簡潔地)「str」和「反向「和僅字符串」反向「功能。 – djhworld

+0

當我想知道爲什麼一些函數需要集合和其他(一系列)獨立參數時,我才意識到這一點。瞭解差異不僅幫助我使用其他功能,而且決定如何參數化我自己的功能。這就是爲什麼我認爲對一個「簡單問題」進行更詳細的闡述可能對其他人有用。 – NielsK

+0

一個很好的,詳細的調查,但'(str2'(a「+」b「=」(+ a b)))「例子是一個稻草人。將它寫爲'(str2 [a「+」b「=」(+ a b)])',或者使用'(list ...)'而不是'[']''將會很簡單。如您所見,現有版本對於常見用例更方便,因此我們使用它;但沒有理由我們不能*以另一種方式去做,你似乎暗示了這一點。 – amalloy