我有以下使用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
或者我应该使用别的东西吗?
答案 0 :(得分:2)
我在Leon Grapenthin's answer的评论中提到的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
。
答案 1 :(得分:2)
您可以根据(defn take-while+
[pred coll]
(lazy-seq
(when-let [[f & r] (seq coll)]
(if (pred f)
(cons f (take-while+ pred r))
[f]))))
的来源
dispatch_sync
答案 2 :(得分:1)
常用方法是使用split-with
,它会在向量中返回take-while
和drop-while
的结果。然后,您可以附加drop-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))))))
答案 3 :(得分:0)
我首先创建一个谓词结果的向量,然后根据需要进行处理:
(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)
答案 4 :(得分:0)
以下是换能器版本:
(defn take-while+
([pred]
(fn [rf]
(fn
([] (rf))
([result] (rf result))
([result input]
(if (pred input)
(rf result input)
(reduced (conj! result input))))))))