简体   繁体   English

在clojure中分组一系列bool?

[英]Grouping a sequence of bools in clojure?

I would like to transform the following sequence: 我想改变以下顺序:

(def boollist [true false false false true false true])

Into the following: 进入以下:

[[true] [false false false true] [false true]]

My code leads to a Stackoverflow: 我的代码导致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)))))

Is there an elegant way of transforming this? 是否有一种优雅的方式来改变这种情况?

There's probably a much more elegant way, but this is what I came up with: 可能有更优雅的方式,但这就是我提出的方法:

(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)))

It just traverses the sequence keeping track of the current vector of falses, and a big accumulator of everything so far. 它只是遍历序列,跟踪当前的谬误向量,以及迄今为止所有内容的大累加器。

A short, "clever" solution would be: 一个简短的“聪明”解决方案是:

(defn sep [lst]
  (let [x (partition-by identity lst)]
    (filter last (map concat (cons [] x) x))))

The "stack overflow" issue is due to the philosophy of Clojure regarding recursion and is easily avoided if approached correctly. “堆栈溢出”问题是由于Clojure关于递归的原理,并且如果正确接近则很容易避免。 You should always implement these types of functions* in a lazy way: If you can't find a trick for solving the problem using library functions, as I did above, you should use "lazy-seq" for the general solution (like pmjordan did) as explained here: http://clojure.org/lazy 你应该总是以懒惰的方式实现这些类型的函数*:如果你找不到使用库函数解决问题的技巧,就像我上面所做的那样,你应该使用“lazy-seq”作为一般解决方案(比如pmjordan)如此解释: http//clojure.org/lazy

* Functions that eat up a list and return a list as the result. *占用列表并返回列表作为结果的函数。 (If something other than a list is returned, the idiomatic solution is to use "recur" and an accumulator, as shown by dfan's example, which I would not consider idiomatic in this case.) (如果返回列表以外的其他内容,惯用解决方案是使用“recur”和累加器,如dfan的示例所示,在这种情况下我不会认为是惯用的。)

Here's a version that uses lazy evaluation and is maybe a little more readable: 这是一个使用延迟评估的版本,可能更具可读性:

(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))))))

It doesn't return vectors though, so if that's a requirement you need to manually pass the result of concat and of the function itself to vec , thus negating the advantage of using lazy evaluation. 它不会返回向量,所以如果这是一个要求,你需要手动将concat和函数本身的结果传递给vec ,从而否定了使用延迟求值的优势。

The stack overflow error is because your recur is outside of the if. 堆栈溢出错误是因为您的重复在if之外。 You evaluate the if form for side effects , then unconditionally recur. 您评估副作用的if形式,然后无条件地重复。 (feel free to edit for format, I'm not at a real keyboard). (随意编辑格式,我不是真正的键盘)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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