Tuesday, December 8, 2009

uses for take/drop-while

I've found a use for take-while & drop-while in a map.

To start let's define the following

user=>(defn sort-map [m] (apply sorted-map (apply concat m)))

That's right. A function to cast hash-map to tree-maps.

user=>(sort-map {3 :a 1 :c 2 :b})
{1 :c, 2 :b, 3 :a}

Why would I do that? Because I now have a way of making subsets based on the keys.

user=>(keys-pred take-while #(< 2 %) (sort-map {3 :a 1 :c 2 :b}))
{1 :c}

user=>(keys-pred drop-while #(< 2 %) (sort-map {3 :a 1 :c 2 :b}))
{2 :b, 3 :a}

So, when would this have an application?




Let's define the following map

;Defined in terms of pennies to avoid float error
(def xkcd
(sorted-map-by
(comp - compare)
215 :fruit
275 :fries
335 :salad
355 :wings
420 :cheeze
580 :sampler))
;Assume seq-utils is used
(defn order
([amt menu] (distinct (flatten (vector (order amt menu {})))))
([amt menu items]
(let [affordable (keys-pred drop-while #(< amt %) menu)
exact-entry? (affordable amt)]
(cond
(empty? affordable) {}
exact-entry? (merge-with + items {exact-entry? 1})
true
(remove empty?
(set
(map
#(let [next-amt (- amt (key %))
next-items (merge-with + items {(val %) 1})]
(order next-amt affordable next-items))
affordable)))))))
user=>(order 1505 xkcd)
({:fruit 1, :wings 2, :sampler 1} {:fruit 7})
view raw order.clj hosted with ❤ by GitHub


And there you go, a use for take/drop while with maps :)

No comments:

Post a Comment