如何在 Clojure 中构建字符串



假设我有一个像[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 ...)更惯用。 你可以使用序列函数(interleaveinterposerepeatcycle、...(的全部丰富挂毯,并将结果提取为带有(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"

最新更新