反转字符串(简单问题)

djh*_*rld 18 clojure

在Clojure中有更好的方法吗?

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

daniel=> (apply str (vec (reverse "Hello")))
"olleH"
Run Code Online (Sandbox Code Playgroud)

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

sku*_*uro 26

你最好用clojure.string/reverse:

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

更新:对于好奇,请遵循clojure.string/reverseClojure(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 "")))
Run Code Online (Sandbox Code Playgroud)


Nie*_*lsK 18

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

(doc reverse)

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

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

(reverse "Hello")
Run Code Online (Sandbox Code Playgroud)

并返回一个

(\o \l \l \e \H)
Run Code Online (Sandbox Code Playgroud)

现在,如果我们只是替换集合的函数,您可以发现差异:

(str '(\o \l \l \e \H) )
"(\\o \\l \\l \\e \\H)"
Run Code Online (Sandbox Code Playgroud)

(str \o \l \l \e \H )
"olleH"
Run Code Online (Sandbox Code Playgroud)

两者之间的巨大差异是参数的数量.在第一个示例中,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.
Run Code Online (Sandbox Code Playgroud)

因此,当您提供一个参数(集合)时,所有str返回都是集合的toString.但要获得所需的结果,您需要将5个字符作为单独的参数提供给str,而不是集合本身.Apply是用于"进入"集合并实现此功能的函数.

(apply str '(\o \l \l \e \H) )
"olleH"
Run Code Online (Sandbox Code Playgroud)

在Clojure中经常可以看到处理多个独立参数的函数,因此最好知道何时以及为什么需要使用apply.另一方面要意识到,为什么str函数的编写者接受了多个参数而不是集合?通常,这是一个很好的理由.str函数的流行用例是什么?不肯定地连接单独字符的集合,而是连接值,字符串和函数结果.

(let [a 1 b 2]
  (str a "+" b "=" (+ a b)))
"1+2=3"
Run Code Online (Sandbox Code Playgroud)

如果我们有一个str接受一个集合作为参数怎么办?

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

(str2 (reverse "Hello"))
"olleH"
Run Code Online (Sandbox Code Playgroud)

很酷,它的作品!但现在:

(let [a 1 b 2]
  (str2 '(a "+" b "=" (+ a b)))
  )
"a+b=(+ a b)"
Run Code Online (Sandbox Code Playgroud)

嗯,现在该怎么解决?:)

在这种情况下,使str接受在执行str函数之前计算的多个参数,这给出了最简单的语法.无论何时需要在集合上使用str,apply都是将集合转换为单独参数的简单方法.

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


Joo*_*aat 10

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

(应用str(反向"你好"))

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