2011-11-29 22 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]]