假设我有一个像[1 2 3]
这样的元素列表,我想将其转换为|1|2|3|
。 或者,如果我想在"---------"
中重复该序列"---"
3 次.
我应该如何处理它,以便我可以将其构建成这样的字符串。有没有类似于Java的StringBuilder的方法?我不是在寻找这个问题的具体答案,而只是关于如何在 Clojure 中构建字符串的一般指导,因为我对该语言非常陌生。
从 Clojure 备忘单开始。 查看"字符串"部分。 一些例子:
(str/join | [1 2 3]) => "1|2|3"
(apply str (repeat 3 "---")) => "---------"
(str
"|"
(str/join | [1 2 3])
"|")
=> "|1|2|3|"
除了clojure.string
之外,还有其他库包含许多有用的字符串函数:
- 图珀洛·克洛朱尔图书馆。 查看 tupelo.string 和 tupelo.chars 部分
- 库尔达斯图书馆
- 看起来在"字符串操作"下的 clojure-toolbox.com 中列出了更多 内容
此外,Clojure Core Library 中还有 CL 格式函数,它是 Common Lisp 令人惊叹的format
工具的端口。
(require '[clojure.pprint :refer [cl-format]])
user> (cl-format nil "~v@{~a~:*~}" 5 "10")
;;=> "1010101010"
user> (cl-format nil "|~{~a|~}" [1 2 3])
;;=> "|1|2|3|"
这个真的很强大,但是在非常复杂的字符串处理模板的情况下,格式字符串对于读者来说可能会变得相当复杂。尽管如此,对于您询问的情况(连接、重复、迭代或条件输出(,它仍然在可理解的范围内。
这里有一些例子,很容易从CL翻译成Clojure。
附注:
user> (cl-format nil "~r" 234598284579147)
;;=> "two hundred thirty-four trillion, five hundred ninety-eight billion, two hundred eighty-four million, five hundred seventy-nine thousand, one hundred forty-seven"
user> (cl-format nil "~@r" 1232)
;;=> "MCCXXXII"
使用(apply str ...)
的答案通常是最好的。 但这里有一个额外的技术,以及关于(apply str ...)
中三个点的"专业提示"。
如果字符串的内容最自然地由print
函数生成(您的特定示例并非如此!(,那么您可以使用with-out-str
捕获它:
(with-out-str
(doseq [i (range 1 4)]
(print "|")
(print i))
(println "|")) ;; => "|1|2|3|n"
通常,(apply str ...)
更惯用。 你可以使用序列函数(interleave
、interpose
、repeat
、cycle
、...(的全部丰富挂毯,并将结果提取为带有(apply str ...)
的字符串。 但是,如果序列包含嵌套序列,您将面临挑战。 我们在这里提到这个挑战,因为有两种特定于构建字符串的解决方案。
需要明确的是,嵌套序列在各个方面都"工作正常",除了str
对序列执行的操作可能不是您想要的。 例如,要构建"1------2------3":
;; not quite right:
(apply str
(interpose
(repeat 2 "---")
(range 1 4))) ;; => "1("---" "---")2("---" "---")3"
问题是repeat
生成了一个序列,interpose
尽职尽责地卡在较大序列中的数字之间,并且在处理较大序列时str
尽职尽责地用 Clojure 语法编写嵌套序列。 为了更好地控制嵌套序列的字符串化方式,您可以将(repeat 2 "---")
替换为(apply str (repeat 2 "---"))
。 但是,如果apply str
内的apply str
模式一遍又一遍地发生,则会损害程序的信噪比。 一个可能更干净的替代方案是flatten
函数(也许这是它唯一的惯用法(:
(apply str
(flatten
(interpose
(repeat 2 "---")
(range 1 4)))) ;; => "1------2------3"