假设我有一个单字符串的惰性序列,仅包含“A”“B”和“C”。
我想从中创建第二个序列,其中包含每个“A”与直接跟随“A”的尽可能多的“B”连接。
例如,输入序列“C”“B”“A”“B”“B”“A”“A”“B”“C”将产生序列“ABB”“A”“AB”。
假设我有一个单字符串的惰性序列,仅包含“A”“B”和“C”。
我想从中创建第二个序列,其中包含每个“A”与直接跟随“A”的尽可能多的“B”连接。
例如,输入序列“C”“B”“A”“B”“B”“A”“A”“B”“C”将产生序列“ABB”“A”“AB”。
这是一种方法:
(defn austin [coll]
(lazy-seq
(when-let [[x & xs] (seq coll)]
(if (= x "A")
(let [[bs other] (split-with #(= % "B") xs)]
(cons (apply str x bs) (austin other)))
(austin xs)))))
(austin '("C" "B" "A" "B" "B" "A" "A" "B" "C")) ;=> ("ABB" "A" "AB")
首先,我们when-let
要么将输入集合解构为它的第一个和其余部分(x
和xs
),要么返回nil
- 终止递归 - 如果coll
为空。
接下来,我们检查是否x
为"A"
。如果是,我们使用split-with
将剩余的项目分成两个 seq,一个"B"
是紧随其后的任何 s,另一个是其他所有的。然后,我们使用str
将s 与我们找到的"A"
任何s 组合到该过程的递归延续中。"B"
cons
这可能不是最好的解决方案,但这里是使用clojure.core/for
.
(def abc '("C" "B" "A" "B" "B" "A" "A" "B" "C"))
=> #'user/abc
(for [i (range (count abc))
:let [a (nth abc i)]
:when (= a "A")]
(apply str a (for [j (range (inc i) (count abc))
:let [b (nth abc j)]
:while (= b "B")]
b)))
=> ("ABB" "A" "AB")