2011-10-29 44 views
5

我有一個簡單的Common Lisp問題:從字符串列表中刪除重複項的慣用方法是什麼?從列表中刪除重複的字符串

remove-duplicates作品我期望的數字,而不是字符串:

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

(1 2 3) 

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

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

我猜有一些感覺,即字符串不相等,很可能是因爲雖然「富「和」foo「顯然是相同的,它們實際上是指向內存中不同結構的指針。我想我的期望可能只是C宿醉。

回答

17

你必須告訴remove-duplicates它應該如何比較值。默認情況下,它使用eql,這不足以用於字符串。傳遞:test功能,如:

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

(編輯以解決意見的問題):作爲一種替代equal,你可以在這個例子中使用string=。這個謂詞(在某種程度上)不如equal通用,它可能(可能最終可能最終......)因此會更快。一個真正的好處可能是,那string=可以告訴你,如果你傳遞一個錯誤的值:

(equal 1 "foo") 

高興地產生nil,而

(string= 1 "foo") 

給出了一個type-error條件。但是請注意,這

(string= "FOO" :FOO) 

是完全明確定義(string=和其朋友在「字符串代號」不是字符串來定義),所以類型安全就只能到此爲止這裏。

另一方面,標準的eql謂詞幾乎從來都不是比較字符串的正確方法。如果您熟悉Java語言,請將eql視爲使用==,而將equal(或string=等)調用equals(Object)方法。雖然eql做了一些類型的自省(與eq不同),但對於大多數(非數字)lisp類型,eql歸結爲類似於指針比較的東西,但如果您想根據它們實際上包含的內容,而不僅僅是它們在內存中的位置。

對於更Python傾斜,eq(和eql用於非數字類型)是更像is操作者,而equal更像==它調用__eq__

+0

我會試圖使用STRING =而不是EQUAL。 – Vatine

+1

爲什麼?有什麼不同? – rivasket

+0

STRING =使用根據[HyperSpec](http://www.lispworks.com/documentation/HyperSpec/Body/f_chareq.htm#char-equal)的CHAR =比較字符「...如果所有字符都是如果兩個字符在任何實現定義的屬性中不同,那麼它們不是char =「。我不確定使用實現定義的行爲是一個更好的選擇。 –

相關問題