假设我有一个带有两个项的谓词并返回true为false。我想在序列中的每个连续对之间插入一个项目,该序列对谓词返回true。我想出了几个解决方案,但我想知道在Clojure中实现它的惯用方法是什么?
答案 0 :(得分:4)
我的第一稿似乎是
(defn insert-between [pred inter coll]
(lazy-seq
(when-let [s (seq coll)]
(cons (first s)
(mapcat (fn [[left right]]
(if (pred left right)
[inter right]
[right]))
(partition 2 1 s))))))
user> (insert-between < :less [1 6 7 4 3])
(1 :less 6 :less 7 4 3)
似乎工作,但我很特别 - 以丑陋的方式包装第一个元素,我认为你可以解决这个问题。无论如何,解决方案肯定可以改进。
答案 1 :(得分:3)
这是我的尝试:
(defn interpose-predicated [pred in coll]
(if (next coll)
(->> coll
(partition 2 1)
(mapcat (comp next #(if (apply pred %) (interpose in %) %)))
(cons (first coll)))
coll))
答案 2 :(得分:3)
通常的SO [clojure]比赛提出了最简洁的解决方案。 :-)我通常不会赢,但我在这个过程中学到了很多东西。无论如何,这是我的解决方案:
(defn interpose-p [[a b & _ :as s] d p]
(when-not (empty? s)
(if (and (not (nil? b)) (p a b))
(cons a (cons d (interpose-p (rest s) d p)))
(cons a (interpose-p (rest s) d p)))))
(interpose-p [1 2 3 2 1 2 3] "," <)
(1 "," 2 "," 3 2 1 "," 2 "," 3)
更新:即使讨论结束,这里还有一个更新的解决方案,考虑到每个人的评论。假设我对lazy-seq的理解是正确的,这个时间应该是相当的工业强度。它与lazy-seq讨论here有关。
(defn interpose-p
[pred coll sep]
(let [f (fn [c]
(when-let [[a b & _ :as s] (seq c)]
(if (and b (pred a b))
(list* a sep (interpose-p pred (rest s) sep))
(list* a (interpose-p pred (rest s) sep)))))]
(lazy-seq (f coll))))