在Clojure中加入多个懒惰的字符串序列

时间:2012-08-22 09:39:15

标签: string clojure concatenation lazy-sequences

我有几个字符串:

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

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

(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))) - 但这是最​​正确的方法吗?

3 个答案:

答案 0 :(得分:6)

您可能希望使用更多更高效的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 - 这是substring包装的Java subs方法的行为。如果您立即将"s"移至subs并且不保留其他任何引用,则这不是问题,因为join会在拉出字符后将其丢弃。

如果你最终使用懒惰的字符序列,那么除了使用(map (partial apply str) [...your vector here...])之类的东西将clojure.string/join的输入转换成字符串之外,没有什么可以做的。

答案 1 :(得分:1)

尝试这一点,是的,因为你的代码的结果不合适,懒惰就是懒惰。

(str (apply str (take 4 a)) " " (apply str (take-last 4 b)))

答案 2 :(得分:1)

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