2011-11-29 58 views
10

Tôi mới sử dụng Clojure và lập trình chức năng nói chung. Tôi đang thua lỗ trong cách xử lý điều này theo cách chức năng.Xoay ma trận danh sách danh sách trong Clojure

Tôi có ma trận sau:

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

tôi muốn biến nó thành một cái gì đó như thế này (xoay ngược chiều kim đồng):

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

tôi đã bị hack lên chút này mà mang lại cho tôi những yếu tố theo đúng thứ tự. Nếu tôi có thể thu thập dữ liệu trong một chuỗi theo cách này thì tôi có thể chia nó thành phân vùng. Tuy nhiên tôi khá chắc chắn liều lượng là sai đường dẫn:

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

Tôi đã theo dõi các cuộc gọi bản đồ lồng nhau nhưng vẫn bị kẹt với điều đó. Cách chính xác để xây dựng một chuỗi trong Clojure hoặc xử lý điều này một cách tốt hơn là gì?

Trả lời

30

Điều bạn đang cố gắng đạt được các âm thanh như transpose. Tôi muốn đề xuất

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

Nó làm gì?

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

tương đương với

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

mà mất yếu tố đầu tiên của mỗi trong ba danh sách, gọi danh sách trên chúng, sau đó đưa các yếu tố thứ hai, gọi là danh sách trên chúng ... An trả về một chuỗi các tất cả các danh sách được tạo theo cách này.

Một vài ví dụ khác về cả hai applymap có thể được tìm thấy trên ClojureDocs.

+0

ấn tượng! cảm ơn – JustGage

9

Lấy giải pháp matrix transposition trực tiếp từ rosettacode:

(vec (apply map vector matrix))

Để xem những gì đang xảy ra xem xét:

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

này sẽ làm việc độc đáo với kích thước ma trận tùy ý mặc dù nó không phải là tốt cho đáng kể số crunching, cho rằng bạn sẽ muốn xem xét sử dụng một java dựa trên ma trận thao tác thư viện từ Clojure.

+0

rosettacode trông thx tuyệt vời cho chỉ có – jm0

2

Dưới đây là một cách:

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

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

Đó sẽ cho kết quả tương tự như ban đầu của bạn (in các cột của matrix).

5

Bạn có thể sử dụng core.matrix để thực hiện các loại thao tác ma trận này một cách dễ dàng. Đặc biệt, đã có một chức năng transpose thực hiện chính xác những gì bạn muốn:

Ví dụ:

(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]] 
Các vấn đề liên quan