Соедините несколько ленивых последовательностей строк в Clojure
У меня есть несколько строк:
(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))
Это потому что функции take
а также take-last
вернуть ленивые последовательности. Вопрос в том, как правильно объединить несколько ленивых последовательностей строк и вернуть одну строку?
Изменить: я нашел одно решение - (apply str (concat (take 4 a) " " (take-last 4 a)))
- но это самый правильный путь?
3 ответа
Вместо того, чтобы использовать функции последовательности для среза входных строк, вы можете использовать гораздо более эффективные 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
в строки.
(str/join " " (map (fn [f col] (f col))
[first last]
(map #(str/split % #" ") [a b])))
Попробуйте это, и да, потому что лень результат вашего кода не является правильным.
(str (apply str (take 4 a)) " " (apply str (take-last 4 b)))