2

我有几个字符串:

(def a "some random string")
(def b "this is a 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)))但它是最正确的方法吗?

4

3 回答 3

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中——这是 Java包装substring方法的行为subs)。如果您立即将其"s"交给subs并且不保留对它的其他引用,这不是问题,因为join在拉出字符后会丢弃它。

毕竟,如果您最终确实使用了惰性字符序列,那么除了使用(map (partial apply str) [...your vector here...])将输入转换clojure.string/join为字符串之类的方法外,别无他法。

于 2012-08-22T09:54:36.200 回答
1

试试这个,是的,因为你的代码结果不正确,因为懒惰。

(str (apply str (take 4 a)) " " (apply str (take-last 4 b)))
于 2012-08-22T09:56:38.660 回答
1
(str/join " " (map (fn [f col] (f col))
               [first last]
               (map #(str/split % #" ") [a b])))
于 2012-08-23T05:52:39.190 回答