2011-10-29 59 views
5

Tôi có một câu hỏi đơn giản thường gặp về Lisp chết: cách thành ngữ để xóa các từ khóa trùng lặp khỏi danh sách các chuỗi là gì?Xóa các chuỗi trùng lặp khỏi danh sách

remove-duplicates công trình như tôi mong đợi cho con số, nhưng không phải cho chuỗi:

* (remove-duplicates '(1 2 2 3)) 

(1 2 3) 

* (remove-duplicates '("one" "two" "two" "three")) 

("one" "two" "two" "three") 

Tôi đoán có một số quan niệm rằng dây không bằng nhau, rất có thể vì mặc dù "foo "và" foo "có vẻ giống hệt nhau, chúng thực sự trỏ tới các cấu trúc khác nhau trong bộ nhớ. Tôi nghĩ rằng kỳ vọng của tôi ở đây có thể chỉ là một sự nôn nao của C.

Trả lời

17

Bạn phải thông báo cho các vị trí loại bỏ trùng lặp cách so sánh các giá trị. Theo mặc định, nó sử dụng eql, không đủ cho chuỗi. Vượt qua :test chức năng như trong:

(remove-duplicates your-sequence :test #'equal). 

(Chỉnh sửa để giải quyết các câu hỏi từ những ý kiến): Là một thay thế cho equal, bạn có thể sử dụng string= trong ví dụ này. Vị từ này là (theo một cách) ít chung chung hơn equal và nó có thể (có thể, có thể, có thể, cuối cùng ...) do đó sẽ nhanh hơn. Một lợi ích thực sự có thể, rằng string= có thể cho bạn biết, nếu bạn vượt qua một giá trị sai:

(equal 1 "foo") 

hạnh phúc mang lại nil, trong khi

(string= 1 "foo") 

đưa ra một điều kiện type-error. Lưu ý, mặc dù, rằng

(string= "FOO" :FOO) 

là hoàn toàn được xác định rõ (string= và người bạn của nó được xác định theo "định danh chuỗi" không dây), do đó gõ an toàn sẽ đi chỉ cho đến nay đây.

Thuộc tính chuẩn eql, mặt khác, gần như không bao giờ đúng cách để so sánh chuỗi. Nếu bạn đã quen thuộc với ngôn ngữ Java, hãy nghĩ đến eql khi sử dụng == trong khi equal (hoặc string=, v.v.) gọi phương thức equals(Object). Mặc dù eql thực hiện một số kiểu introspection (trái ngược với eq, không), đối với hầu hết các loại không phải dạng số, eql ghi lại thứ gì đó giống như so sánh con trỏ, không đủ, nếu bạn muốn phân biệt các giá trị dựa trên những gì họ thực sự chứa, và không chỉ đơn thuần là nơi họ đang ở trong bộ nhớ.

Đối với nhiều Pythonic nghiêng, eq (và eql với nhiều loại không phải số) là giống như các nhà điều hành is, trong khi equal là giống như == trong đó kêu gọi __eq__.

+0

Tôi sẽ bị cám dỗ sử dụng STRING = thay vì EQUAL. – Vatine

+1

Tại sao? Sự khác biệt là gì? – rivasket

+0

STRING = so sánh các ký tự sử dụng CHAR = theo [HyperSpec] (http://www.lispworks.com/documentation/HyperSpec/Body/f_chareq.htm#char-equal) "... trả về true nếu tất cả các ký tự Nếu hai ký tự khác nhau trong bất kỳ thuộc tính được xác định nào, thì chúng không phải là char = ". Tôi không chắc chắn bằng cách sử dụng một hành vi thực hiện xác định là một sự lựa chọn tốt hơn. –

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