我有一个表格的数据结构["a" "b" " c" "d" " e" " f" "g"]
我想将其简化为["a" "b c" "d e f" "g"]
,即以空格开头的字符串连接到它们前面的字符串。
我已经为此苦苦挣扎了几个小时,正在寻找一些灵感!
这会将字符串序列拆分为块,然后将所有应该连接的字符串组与string/join
每个组的单个调用连接起来,因此它避免了解决方案将字符串一个一个粘贴在一起的二次行为:
(def xs ["a" "b" " c" "d" " e" " f" "g"])
(require '[clojure.string :as string])
(->> xs
(partition-by #(.startsWith ^String % " "))
(map vec)
(partition-all 2)
(reduce (fn [acc [ps ss]]
(-> acc
(into (pop ps))
(conj (string/join "" (cons (peek ps) ss)))))
[]))
;= ["a" "b c" "d e f" "g"]
请注意,这假定第一个字符串不以空格开头。为了消除这个假设,您可以在前面添加一个空字符串((cons "" xs)
而不是xs
在上面,或者(cons "")
作为->>
第一步)来“捕捉”它们。在这种情况下,结果将以一个字符串开头,该字符串由以空格开头的序列初始字符串连接在一起,或者如果序列不以此类字符串开头,则为一个空格,因此您可以检查""
第一个位置是否存在结果并可能将其过滤掉。
过滤器和初始累加器处理第一个的混合方法从空间案例开始。
(defn join-when-space [vs]
(mapv (partial apply str)
(filter not-empty
(reduce (fn [a s] (if (re-find #"^\s" s)
(conj (pop a) (conj (peek a) s))
(conj a [s])))
[[]] vs))))
以下是使用 的一种方法reduce
,尽管可能有一种更优雅的方法来做同样的事情 - Clojure 中经常有 :)
(defn join-when-space [v]
(->> (reduce (fn [acc next-value]
(if (re-matches #"^ .*" next-value)
(concat (butlast acc) [(str (last acc) next-value)])
(concat acc [next-value])))
[[] (first v)] (rest v))
rest
(into [])))
此函数生成拼接在初始空格上的序列字符串的惰性序列:
(defn spliced-seq [strings]
(let [[x & xs] strings]
(if (empty? xs)
[x]
(let [[ys & ns] (split-with #(.startsWith % " ") xs)]
(cons (apply str x ys) (lazy-seq (f ns)))))))
然后(vec (spliced-seq) ["a" " b" " c" "d" "e"]))
产生["a b c" "d e"]
.