2011-11-29 15 views
10

Sono nuovo di Clojure e programmazione funzionale in generale. Sono in perdita su come gestirlo in modo funzionale.Ruota una matrice list-of-list in Clojure

ho la seguente matrice:

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

voglio trasformarlo in qualcosa di simile (ruotare in senso antiorario):

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

Ho messo in questo pezzo che mi dà gli elementi nell'ordine corretto. Se potessi raccogliere i dati in una stringa in questo modo, potrei dividerlo con la partizione. Comunque sono abbastanza sicuro doseq è la strada sbagliata:

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

ho dilettato con chiamate mappa nidificate, ma continuo a rimanere bloccati con quello. Qual è il modo corretto di costruire una stringa in Clojure o gestirla in un modo ancora migliore?

risposta

30

Quello che stai cercando di ottenere suoni come transpose. Suggerirei

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

Che cosa fa?

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

è equivalente a

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

che prende primi elementi di ciascuna delle tre liste, invita lista sopra, poi prende secondi elementi, invita lista sopra ... Un restituisce una sequenza di tutte le liste che sono state generate in questo modo.

Un altro paio di esempi sia di apply e di map possono essere trovati su ClojureDocs.

+0

Impressionante! Grazie – JustGage

9

Prendendo la soluzione matrix transposition direttamente da rosettacode:

(vec (apply map vector matrix))

per vedere cosa sta succedendo considerare:

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

Questo funziona bene con dimensioni della matrice arbitrarie anche se non è buono per significativo numero di crunch, per cui si vorrebbe considerare l'utilizzo di una libreria di manipolazione di matrici basata su Java da Clojure.

+0

rosettacode sembra thx impressionante per indicare ci – jm0

2

Ecco un modo:

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

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

che produce lo stesso output come l'originale (stampa le colonne di matrix).

5

È possibile utilizzare core.matrix per eseguire facilmente questo tipo di manipolazione della matrice. In particolare, v'è già una funzione transpose che fa esattamente ciò che si vuole:

Esempio:

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