[英]Grouping a sequence of bools in clojure?
我想改变以下顺序:
(def boollist [true false false false true false true])
进入以下:
[[true] [false false false true] [false true]]
我的代码导致Stackoverflow:
(defn sep [boollst]
(loop [lst boollst
separated [[]]
[left right] (take 2 lst)]
(if (nil? left) separated)
(recur (next lst)
(if (false? left)
(conj (last separated) left)
(conj separated [left]))
(take 2 (next lst)))))
是否有一种优雅的方式来改变这种情况?
可能有更优雅的方式,但这就是我提出的方法:
(defn f
([xs] (f xs [] []))
([[x & xs :as all] acc a]
(if (seq all)
(if x
(recur xs [] (conj a (conj acc x)))
(recur xs (conj acc x) a))
a)))
它只是遍历序列,跟踪当前的谬误向量,以及迄今为止所有内容的大累加器。
一个简短的“聪明”解决方案是:
(defn sep [lst]
(let [x (partition-by identity lst)]
(filter last (map concat (cons [] x) x))))
“堆栈溢出”问题是由于Clojure关于递归的原理,并且如果正确接近则很容易避免。 你应该总是以懒惰的方式实现这些类型的函数*:如果你找不到使用库函数解决问题的技巧,就像我上面所做的那样,你应该使用“lazy-seq”作为一般解决方案(比如pmjordan)如此解释: http : //clojure.org/lazy
*占用列表并返回列表作为结果的函数。 (如果返回列表以外的其他内容,惯用解决方案是使用“recur”和累加器,如dfan的示例所示,在这种情况下我不会认为是惯用的。)
这是一个使用延迟评估的版本,可能更具可读性:
(defn f [bools]
(when-not (empty? bools)
(let
[[l & r] bools
[lr rr] (split-with false? r)]
(lazy-seq (cons
(cons l lr)
(f rr))))))
它不会返回向量,所以如果这是一个要求,你需要手动将concat和函数本身的结果传递给vec
,从而否定了使用延迟求值的优势。
堆栈溢出错误是因为您的重复在if之外。 您评估副作用的if形式,然后无条件地重复。 (随意编辑格式,我不是真正的键盘)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.