2011-07-06 18 views
5

Tengo una lista de puntos x, y almacenados como un vector de vectores, y quiero averiguar los límites.obteniendo los límites de una lista de puntos x, y

Por ejemplo, dada la siguiente:

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

El resultado sería:

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

Esto es lo que tengo hasta ahora. Da el resultado deseado, pero parece detallado y no muy clojure-ey para mí.

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

¿Alguna idea sobre cómo mejorar? ¡Gracias!

Respuesta

3

Si ya estoy usando vectores para los puntos de entrada, me gustaría que el valor de retorno esté en el mismo formato. Con esto en mente, creo que esta es una buena solución idiomática:

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

¡Asignando "primero" y "segundo" a la lista para obtener algo ordenable! ¡Por supuesto! ¡Gracias! – jhickner

4

¡Su solución ya es bastante buena! Es bastante idiomático y también es O (n) en el número de puntos que es algorítmicamente óptimo (mejor en realidad que un método que hace una clasificación).

Pero aquí es una forma alternativa de hacerlo que puede encontrar interesante .... creado principalmente porque soy un gran fan de funciones de orden superior :-)

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

¡Definitivamente interesante! Me tomó un tiempo seguir cómo funciona. ¡Muy genial! – jhickner

1

No creo que su solución no clojure-ey también. Pero si te gusta menos código, puedes probar un conjunto ordenado.

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

actualización: Lo siento el código anterior no es correcta. Es necesario ordenar separadamente xey para encontrar un límite no máx. O puntos mínimos. John's solution es mejor a menos que se prefiera el juego de juegos.

Cuestiones relacionadas