2011-11-29 22 views
10

Soy nuevo en Clojure y en la programación funcional en general. No sé cómo manejar esto de una manera funcional.Girar una matriz de lista de lista en Clojure

tengo la siguiente matriz:

(def matrix [[\a \b \c] 
      [\d \e \f] 
      [\g \h \i]]) 

quiero transformarlo en algo como esto (girar en sentido antihorario):

((\a \d \g) 
(\b \e \h) 
(\c \f \i)) 

He hackeado este bit que me da los elementos en el orden correcto. Si pudiera recopilar los datos en una cadena de esta manera, podría dividirlos con partición. Sin embargo estoy bastante seguro de doseq es el camino equivocado:

(doseq [i [0 1 2]] 
    (doseq [row matrix] 
    (println (get (vec row) i)))) 

he incursionado con la correspondencia de llamadas anidadas, pero sigo siendo pegado con eso. ¿Cuál es la forma correcta de construir una cuerda en Clojure o manejar esto de una mejor manera?

Respuesta

30

Lo que intentas lograr suena como transpose. Sugeriría

(apply map list matrix) 
; => ((\a \d \g) (\b \e \h) (\c \f \i)) 

¿Qué hace?

(apply map list '((\a \b \c) (\d \e \f) (\g \h \i))) 

es equivalente a

(map list '(\a \b \c) '(\d \e \f) '(\g \h \i)) 

que tiene primeros elementos de cada una de las tres listas, la lista de las llama, entonces toma el segundo elemento, lista de llamadas en ellos ... Un devuelve una secuencia de todas las listas que se generaron de esta manera.

Un par de ejemplos más de ambos apply y map se pueden encontrar en ClojureDocs.

+0

impresionante! Gracias – JustGage

9

Tomando la solución matrix transposition directamente de rosettacode:

(vec (apply map vector matrix))

para ver lo que está pasando en cuenta:

(map vector [\a \b \c] [\d \e \f] [\g \h \i])

Esto funciona muy bien con las dimensiones de la matriz arbitrarias a pesar de que no es bueno para un número significativo de crujidos, para eso querrías considerar usar una biblioteca de manipulación de matrices basada en Java de Clojure.

+0

rosettacode ve THX impresionante para señalar que hay – jm0

2

Aquí hay una manera:

(def transposed-matrix (apply map list matrix)) 
;=> ((\a \d \g) (\b \e \h) (\c \f \i)) 

(doseq [row transposed-matrix] 
    (doall (map println row))) 

que produce el mismo resultado que el original (la impresión de las columnas de matrix).

5

Puede usar core.matrix para realizar este tipo de manipulaciones de matrices con mucha facilidad. En particular, existe ya una función transpose que hace exactamente lo que quiere:

Ejemplo:

(use 'clojure.core.matrix) 

(def matrix [[\a \b \c] 
      [\d \e \f] 
      [\g \h \i]]) 

(transpose matrix) 
=> [[\a \d \g] 
    [\b \e \h] 
    [\c \f \i]]