当谓词为 false 时,需要 while 以包含最后一项



我有以下使用take-while的函数

(defn process [[cash amount wrappers]]
  (let [bought (int (Math/floor (/ cash amount)))
        free (->>
              (iterate (partial unwrapper wrappers) bought)
              (take-while (partial (fn [w a]
                                     (prn (str "a = " a))
                                     (>= a w)
                                     ) wrappers)))]

我遇到的问题是,当谓词为 false 但take-while不返回最后一项时,我想包含最后一项。

有没有办法用take-while解决这个问题,或者我应该使用其他东西?

你可以根据take-while的来源做这样的事情:

(defn take-while+
  [pred coll]
  (lazy-seq
    (when-let [[f & r] (seq coll)]
      (if (pred f)
        (cons f (take-while+ pred r))
        [f]))))

常用的方法是使用 split-with ,它返回向量中take-whiledrop-while的结果。然后,您可以追加drop-while结果的第一个元素。

不过,它需要两次通过。您可能想要编写自定义的 take-while...

(defn take-while-and-one
  [pred coll]
  (lazy-seq
   (when-let [s (seq coll)]
     (if (pred (first s))
       (cons (first s) (take-while-and-one pred (rest s)))
       (list (first s))))))
尝试了

一下我在对Leon Grapenthin的回答的评论中提到的partition-by方法。它通常工作正常,但事实证明,当您使用它创建的一个分区时,partition-by急切地评估下一个分区。因此,虽然这应该是一种懒惰的方法,但它不如他的解决方案那么懒惰,因此无法处理无限序列的边缘情况,其中谓词映射看起来像(true true ... true false false....) 仍然,有趣的实验问题。

(defn take-while-plus-n 
  "Lazily returns successive items from coll while (pred item) returns true,
  then an additional n items. pred must partition coll into segments of finite length."
  [pred n coll]
  (if (pred (first coll))
    (let[[head & tails] (partition-by pred coll)]
      (lazy-cat head (->> tails flatten (take n))))
    (take n coll)))

我扔了可变数量的"附加项目",主要是因为我最终在这两种情况下都使用了take

我将首先创建谓词结果的向量,然后根据需要进行处理:

(def xx (range 10))
;=> (0 1 2 3 4 5 6 7 8 9)
(defn my-tst [arg]
  (< arg 5))
(def flags (mapv my-tst xx))
;=> [true true true true true false false false false false]
(def num-true (count (filter identity flags)))
num-true ;=> 5
(def num-keep (inc num-true))
num-keep ;=> 6
(def keepers (take num-keep xx))
keepers 
;=> (0 1 2 3 4 5)

以下是换能器版本:

(defn take-while+
  ([pred]
   (fn [rf]
     (fn
       ([] (rf))
       ([result] (rf result))
       ([result input]
        (if (pred input)
          (rf result input)
          (reduced (conj! result input))))))))

相关内容

最新更新