2012-11-13 16 views
11

thể trùng lặp:
what is the ‘cons’ to add an item to the end of the list?Thêm vào cuối danh sách trong LISP

Sau khi xem nhiều hướng dẫn về lisp và tìm kiếm cao và thấp trên google cho câu trả lời, tôi vẫn không thể tìm ra cách thêm vào cuối danh sách trong LISP.

Tôi muốn chức năng của mình được thêm 'a vào cuối danh sách '(b c d) nhưng tôi chỉ biết cách thêm nó ở phía trước. Ai đó có thể giúp tôi sử dụng khuyết điểm chính xác để thêm 'a vào cuối danh sách không? Đây là mã của tôi. Cảm ơn trước.

(defun AddRt (a list) 
    (cond 
    ((null list) 
     0) 
    (t 
     (princ (cons a (cons (car list) (cdr list)))) 
    ))) 


(AddRt 'a '(b c d)) 

Trả lời

5

Bạn có thể sử dụng chức năng đệ quy. Ngoài ra, bạn nên tránh sử dụng hiệu trưởng bên trong.

Chức năng sau, endcons, thực hiện chính xác điều tương tự như cons, ngoại trừ giá trị được thêm vào cuối.

(defun endcons (a v) 
    (if (null v) (cons a nil) (cons (car v) (endcons a (cdr v))))) 

(endcons 'a '(b c d)) 

Tất nhiên, bạn cũng có thể sử dụng thêm:

(append '(b c d) '(a)) 

Xem thêm những câu hỏi có liên quan này: what is the 'cons' to add an item to the end of the list?

+0

Nếu tôi không sử dụng hiệu trưởng, làm thế nào tôi nên đi về xuất (endcons 'a' (b c d)) vào màn hình? Cảm ơn sự giúp đỡ của bạn. – Bert

+0

Bạn có thể sử dụng nguyên tắc sau đó, ví dụ '(princ (endcons 'a' (b c d)))'. Nó luôn luôn là một ý tưởng tồi để xác định một chức năng mà làm một số công việc và đầu ra cùng một lúc: những gì sẽ xảy ra nếu bạn muốn sử dụng nó nhiều lần và không muốn bị khó chịu bởi hàng ngàn dòng rác? Luôn tách biệt «công việc thực» và IO. –

4

Một cách là để đảo ngược danh sách. Thêm phần tử vào đầu danh sách được đảo ngược. Và cuối cùng đảo ngược toàn bộ danh sách.

đang Scheme:

(define (add-to-tail l x) 
    (reverse (cons x (reverse l))) 

Nhưng nếu điều này là một hoạt động bạn cần thường xuyên, sau đó tôi muốn đề nghị bạn tìm thấy một cấu trúc dữ liệu khác ngoài danh sách (đơn liên kết).

+0

Cảm ơn, tôi cũng sẽ thử điều này. – Bert

+1

Tôi tin rằng đây không phải là cách tiếp cận tốt: bạn đang thực hiện 2 lần lặp lại, có thể mất nhiều thời gian trên một số danh sách lớn. –

+1

Đây là một điểm tốt.Đối với một danh sách dài, có thể tốt hơn để thay đổi cặp cuối cùng. OP không chỉ định ngôn ngữ. Trong một ngôn ngữ có danh sách bất biến (liên kết đơn), phương pháp ngược lại hai lần là lựa chọn duy nhất. Đối với các ngôn ngữ có danh sách có thể thay đổi, phương pháp đảo ngược hai lần có thể là một ý tưởng hay cho các danh sách ngắn (không có cách nào để đo điểm chuẩn này). Nếu danh sách được đảo ngược được sử dụng như một phần của một số cấu trúc dữ liệu, nó có thể không thể thay đổi được nó. Cuối cùng cho một danh sách dài có thể thay đổi được sử dụng chỉ một lần, tốt hơn là sử dụng 'reverse! '. – soegaard

11

Hoặc push-last, hoặc sử dụng nconc:

> (defparameter a (list 1 2 3)) 
A 
> (push 4 (cdr (last a))) 
(4) 
> a 
(1 2 3 4) 
> (nconc a (list 5)) 
(1 2 3 4 5) 
> a 
(1 2 3 4 5) 

lưu ý rằng đây là những destructiveoperators, tức là, họ sửa đổi đối tượng mà là giá trị của a, không chỉ là ràng buộc của a .

Đây là lý do tại sao, BTW, bạn nên không bao giờ sử dụng nconc trên danh sách được trích dẫn, như (nconc '(1 2 3) '(4 5 6)).