2010-08-18 40 views
10

Tôi đang cố gắng chuyển đổi danh sách các danh sách; ý kiến ​​của tôi chỉ ra quá trình suy nghĩ.Chuyển danh sách trong Common Lisp

(setq thingie '((1 2 3) (4 5 6) (7 8 9))) ;;test case 

(defun trans (mat) 
    (if (car mat) 
    (let ((top (mapcar 'car mat)) ;;slice the first row off as a list 
      (bottom (mapcar 'cdr mat))) ;;take the rest of the rows 
     (cons top (trans bottom)))) ;;cons the first-row-list with the next-row-list 
    mat) 

(trans thingie) 
=> ((1 2 3) (4 5 6) (7 8 9))   ;;wait what? 

Nhưng, tôi thực sự muốn nó được

((1 4 7) (2 5 8) (3 6 9)) 

Tôi đang làm gì sai?

+0

Điều này được gọi là [ma trận transpose] (http://en.wikipedia.org/wiki/Transpose). – sds

+0

@sds: ... yuuup. Tại sao tôi không thấy rằng 3 năm trước là vượt ra ngoài tôi. Hãy cho tôi một vài phút và tôi sẽ sửa lỗi này. –

Trả lời

23

Có một cách đơn giản cho việc này:

(defun rotate (list-of-lists) 
    (apply #'mapcar #'list list-of-lists)) 

nỗ lực của bạn luôn luôn trở về bản gốc mat. Sửa lỗi thụt lề của bạn và bạn thấy rằng giá trị trả lại từ biểu mẫu if luôn bị vứt bỏ.

Edit: Làm thế nào các công trình này:

  • List mất bất kỳ số lượng các đối số và tạo ra một danh sách của nó. định nghĩa chức năng của nó có thể tưởng tượng về như thế này:

    (defun list (&rest arguments) 
        arguments) ; exploit the automatic &rest construction 
    
  • Mapcar mất một chức năng và bất kỳ số lượng các danh sách, và sau đó tạo ra một danh sách mới của các giá trị được tạo ra bằng cách gọi hàm luôn với một phần tử từ những danh sách. Ví dụ: (mapcar #'foo '((A B) (C D))) sẽ tạo danh sách mới, trong đó phần tử đầu tiên là kết quả của (foo 'A 'C) và kết quả thứ hai là (foo 'B 'D).

  • Apply lấy một trình thiết kế danh sách đối số có thể mở rộng làm đối số cuối cùng. Điều này có nghĩa là nếu bạn đặt danh sách đó làm đối số cuối cùng, danh sách đó có thể "lan truyền" để tạo các đối số riêng lẻ cho hàm. Ví dụ: (apply #'+ '(1 2 3)) có cùng hiệu lực là (+ 1 2 3).

Bây giờ bạn có thể mở rộng dòng:

(apply #'mapcar #'list '((A B) (C D))) 

=>

(mapcar #'list '(A B) '(C D)) 

=>

(list (list 'A 'C) (list 'B 'D)) 

=>

'((A C) (B D)) 
+0

Hnnng. Bạn có thể làm sáng tỏ thêm một chút về lý do xoay vòng của bạn? Tôi không thấy * cách nó tạo ra giải pháp. –

+0

Có vấn đề với một số trường hợp thoái hóa. Thử '(xoay nil)' hoặc '(xoay '(nil))' –

Các vấn đề liên quan