获得x,y点列表的边界

时间:2011-07-06 18:31:37

标签: clojure

我有一个x,y点列表存储为矢量矢量,我想找出界限。

例如,鉴于此:

[[0 0] [20 30] [-50 -70] [200 300]]

结果将是:

{:x -50, :y -70, :x2 200, :y2 300}

这是我到目前为止所拥有的。它给出了理想的结果,但看起来很冗长,而且对我来说并不是很好。

(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)))

有关如何改进它的任何想法?谢谢!

3 个答案:

答案 0 :(得分:4)

你的解决方案已经很不错了!它是相当惯用的,并且在算法上最优的点数上也是O(n)(实际上比进行排序的方法更好)。

但是这里有另一种方法,你可能会发现它很有趣....主要是因为我是高阶函数的忠实粉丝: - )

(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]])))

答案 1 :(得分:3)

如果我已经使用向量作为输入点,我希望返回值采用相同的格式。考虑到这一点,我认为这是一个很好的惯用解决方案:

(defn bounds
  [points]
  (let [xs (sort (map first points))
        ys (sort (map second points))]
    (list [(first xs) (first ys)]
          [(last xs) (last ys)])))

答案 2 :(得分:1)

我不认为你的解决方案也不会出现问题。但是如果你喜欢更少的代码,你可以尝试一个有序的集合。

(let [v [[0 0] [20 30] [-50 -70] [200 300]]
      v-sorted (apply sorted-set v)]
  [(first v-sorted) (last v-sorted)])

更新:很抱歉上面的代码不正确。有必要对separetely x和y进行排序以找到一个不是最大或最小点的边界。除非设置首选,否则约翰的solution会更好。