Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clojure - take-while to include last item when predicate is false

Tags:

clojure

I have the following function that uses 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)))]

The problem I have is that I want to include the last item when the predicate is false but take-while does not return that last item.

Is there a way round that with take-while or should I use something else?

like image 911
dagda1 Avatar asked Dec 24 '22 18:12

dagda1


2 Answers

You could do something like this, based on the source of 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]))))
like image 130
Diego Basch Avatar answered Jan 26 '23 00:01

Diego Basch


The common approach is to use split-with, which returns the results of both take-while and drop-while in a vector. You can then append the first element of the drop-while result.

It requires two passes, though. You might want to write a custom 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))))))
like image 43
Leon Grapenthin Avatar answered Jan 26 '23 00:01

Leon Grapenthin