反转字符串(简单问题)

时间:2011-09-19 10:24:45

标签: clojure

在Clojure中有更好的方法吗?

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

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

每次要将字符串反转回原始格式时,是否必须执行apply $ str $ vec位?

3 个答案:

答案 0 :(得分:26)

您最好使用clojure.string/reverse

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

更新:对于好奇,请遵循Clojure(v1.4)和ClojureScript中clojure.string/reverse的源代码片段

; 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 "")))

答案 1 :(得分:18)

好的,所以使用内部应用就可以很容易地推出自己的函数,或者使用专用的反向版本,它可以更好地(但仅限于)字符串。这里要考虑的主要问题是str函数的arity(参数的数量和类型),以及reverse对集合起作用的事实。

(doc reverse)

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

这意味着反向不仅适用于字符串,也适用于所有其他集合。但是,因为reverse要求将集合作为参数,所以它将字符串视为字符集合

(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是用于“进入”集合并实现此功能的函数。

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

在Clojure中经常可以看到处理多个独立参数的函数,因此最好知道何时以及为什么需要使用apply。另一方面要意识到,为什么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,apply都是将集合转换为单独参数的简单方法。

创建一个接受集合的str并让它评估内部的每个部分将需要更多的努力,仅在不太常见的用例中提供帮助,导致更复杂的代码或语法,或限制它的适用性。因此,可能有更好的方法来反转字符串,但反向,应用和str最适合他们的工作。

答案 2 :(得分:10)

像反向一样,应用于任何可选类型,而不仅仅是矢量,所以

(应用str(反向“你好”))

稍短。但是,clojure.string / reverse应该更有效率。