繁体   English   中英

在clojure中分组一系列bool?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM