Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
clojure-当谓词为false时,花一段时间包含最后一项_Clojure - Fatal编程技术网

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的来源,简化了它,并在结尾添加了向量,而不是返回零。你是对的,我并没有看到分区使用计数,顺便说一句,这也会算作第二次通过…啊,确实如此。当你想最大限度地懒惰时,似乎总是那些小细节把你绊倒。仍然认为你走的是正确的道路:)