2011-11-29 50 views
10

我一般是新來的Clojure和函數式編程。我在如何以功能性的方式處理這個問題上感到不知所措。旋轉列表的列表矩陣Clojure中

我有以下矩陣:

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

我想把它改造成這樣的事情(逆時針旋轉):

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

我砍死了這一點,讓我的元素按正確的順序。如果我可以用這種方式收集字符串中的數據,那麼我可以用分區來分割它。不過我敢肯定doseq是走錯了路:

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

我和嵌套調用的地圖涉獵,但一直被卡住這一點。在Clojure中建立字符串或以更好的方式處理這個字符串的正確方法是什麼?

回答

30

你想實現聽起來像是transpose什麼。我建議

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

它是做什麼的?

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

相當於

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

這需要每三個列表的第一要素,呼籲他們名單,然後採取第二個元素,它們話費清單...一個返回序列所有以這種方式生成的列表。

可以在ClojureDocs上找到更多的兩個例子:applymap

+0

令人印象深刻!謝謝 – JustGage

9

直接從rosettacode服用matrix transposition解決方案:

(vec (apply map vector matrix))

要看看是怎麼回事考慮:

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

這將任意矩陣尺寸很好地工作,雖然這是不好的顯著的數字運算,爲您將要考慮使用Clojure的從一個基於java的矩陣操作庫。

+0

rosettacode看起來真棒THX的指點有 – jm0

2

這裏有一種方法:

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

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

產生相同的輸出作爲您的原始(打印的matrix列)。

5

您可以使用core.matrix非常容易地做這些類型的矩陣操作的。特別是,已經有一個transpose函數,它正是你想要的:

例子:

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