clojure-当谓词为false时,花一段时间包含最后一项
我有以下使用clojure-当谓词为false时,花一段时间包含最后一项,clojure,Clojure,我有以下使用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]
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
或者我应该使用其他方法?常用的方法是使用split with
,它返回向量中take 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))))))
我将首先创建谓词结果的向量,然后根据需要进行处理:
(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)
(def xx(范围10))
;=> (0 1 2 3 4 5 6 7 8 9)
(定义我的tst[arg]
( [真假真假假假]
(def num true(计数(过滤器标识标志)))
num true;=>5.
(def num keep(inc num true))
num keep;=>6.
(def保持器(取数值保持xx))
饲养员
;=> (0 1 2 3 4 5)
尝试了一下我在评论中提到的分区方法。它通常工作正常,但当您使用它所创建的一个分区时,partitionby
急切地计算下一个分区。因此,虽然这应该是一种懒惰的方法,但它没有他的解决方案那么懒惰,因此无法处理谓词映射看起来像(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
根据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]))))
以下是传感器版本:
(defn take-while+
([pred]
(fn [rf]
(fn
([] (rf))
([result] (rf result))
([result input]
(if (pred input)
(rf result input)
(reduced (conj! result input))))))))
您还可以使用分区by
并获取第一个seq加上第二个seq的第一个成员。只经过那里一次。这是个好主意。你应该把它作为一个答案发布:)你能告诉我为什么你克隆了我的答案吗?@LeonGrapenthin我没有克隆你的答案,我在“你可能想写一个自定义的take while”上停止了阅读。然后我查看了take while的来源,简化了它,并在结尾添加了向量,而不是返回零。你是对的,我并没有看到分区使用计数,顺便说一句,这也会算作第二次通过…啊,确实如此。当你想最大限度地懒惰时,似乎总是那些小细节把你绊倒。仍然认为你走的是正确的道路:)