我有几个字符串:
(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))
这是因为函数take
和take-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])))