I have a list of x,y points stored as a vector of vectors, and I want to find out the bounds.
For example, given this:
[[0 0] [20 30] [-50 -70] [200 300]]
The result would be:
{:x -50, :y -70, :x2 200, :y2 300}
Here's what I have so far. It gives the desired result, but seems verbose and not very clojure-ey to me.
(defn get-stroke-bounds [vector-of-points]
(reduce (fn [m [x y]]
{:x (min (:x m Integer/MAX_VALUE) x)
:y (min (:y m Integer/MAX_VALUE) y)
:x2 (max (:x2 m Integer/MIN_VALUE) x)
:y2 (max (:y2 m Integer/MIN_VALUE) y)})
{}
(vector-of-points)))
Any ideas on how to improve it? Thanks!
Your solution is already pretty good! It's fairly idiomatic and is also O(n) in the number of points which is algorithmically optimal (better in fact than a method which does a sort).
But here's an alternative way of doing it you might find interesting.... created mainly because I'm a big fan of higher order functions :-)
(defn get-stroke-bounds [stroke]
(zipmap
[:x :y :x2 :y2]
(map
(fn [[getter reducer]]
(reduce
reducer
(map getter stroke)))
[
[first min]
[second min]
[first max]
[second max]])))
If I am already using vectors for the input points, I'd want the return value to be in the same format. With that in mind, I think this is a good idiomatic solution:
(defn bounds
[points]
(let [xs (sort (map first points))
ys (sort (map second points))]
(list [(first xs) (first ys)]
[(last xs) (last ys)])))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With