在Clojure中连接多个延迟字符串序列



我有几个字符串:

(def a "some random string")
(def b "this is a text")

现在我想把它们的一部分连接起来,创建一个字符串"sometext"。不幸的是,下面的两个字符串都不起作用。

(clojure.string/join " " [(take 4 a) (take-last 4 b)])
(str (take 4 a) " " (take-last 4 b))

这是因为函数taketake-last返回惰性序列。问题是:连接多个延迟字符串序列并返回一个字符串的正确方法是什么?

编辑:我找到了一个解决方案(apply str (concat (take 4 a) " " (take-last 4 a))),但这是最正确的方法吗?

与其使用序列函数对输入字符串进行切片,不如使用效率更高的subs(对于子字符串;请注意,有一个与GC相关的警告,请参阅下文):

(subs "asdf" 1 2)
; => "s"
;; a and b as in the question text
(clojure.string/join " " [(subs a 0 4) (subs b (- (count b) 4))])
; => "some text"

前面提到的警告是,只要第一个例子中返回的"s"仍然不符合垃圾收集的条件,原始"asdf"也不符合垃圾回收的条件(因为subs在不分配新存储的情况下向输入String返回"视图"——这是subs包装的Java的substring方法的行为)。如果您立即将"s"交给subs,并且不保留对它的其他引用,则这不是问题,因为join将在提取字符后丢弃它。

如果您最终使用的是懒惰的字符序列,那么除了使用(map (partial apply str) [...your vector here...])之类的东西将clojure.string/join的输入转换为字符串之外,别无选择。

试试这个,是的,由于懒惰,代码的结果是不正确的。

(str (apply str (take 4 a)) " " (apply str (take-last 4 b)))
(str/join " " (map (fn [f col] (f col))
               [first last]
               (map #(str/split % #" ") [a b])))

最新更新