我有一个["a" "b" " c" "d" " e" " f" "g"]
我想将其减少到["a" "b c" "d e f" "g"]
,也就是说,以空格开头的字符串会加到前面的字符串中。
我已经苦苦挣扎了几个小时,我正在寻找一些灵感!
答案 0 :(得分:2)
这会将字符串序列拆分成块,然后连接所有字符串组,每个字符串应该加入一个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 "")
作为第一个->>
步骤)以“捕获”他们。在这种情况下,结果将以一个字符串开头,这个字符串是将序列初始字符串以空格开头,或者如果序列不以这样的字符串开头,则将空格连接起来,这样就可以检查是否存在""
在结果的第一个位置,可能会过滤掉它。
答案 1 :(得分:1)
以下是使用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 [])))
答案 2 :(得分:1)
混合方法,其中过滤器和初始累加器处理第一个以空格大小写开始。
(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))))
答案 3 :(得分:0)
此函数生成一个在初始空格上拼接的序列 strings 的延迟序列:
(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"]
。