2010-07-27 20 views

回答

9

有兩種方法,找出:

  • ,你可以用數據

  • 測試它,你可以分析你的源代碼

讓我們來看看源代碼。

  • 名單內置聯利弊細胞

  • 長度需要通過列表

  • 行走一次爲您計算的長度FILTER的每一個遞歸調用。壞!

    (ENDP使用代替)

  • 拆卸需要通過列表

  • 行走一次爲你計算REMOVE兩次每次遞歸調用:BAD!

    (代替使用REMOVE上a的,遞歸與REST)

  • 調用FILTER將不一定是優化的尾部呼叫。 在某些實現中,在某些實現中,您可能需要告知編譯器 您想要針對尾部調用進行優化,但在某些實現中,不會有尾部調用優化可用。如果沒有,那麼你得到一個堆棧 溢出足夠長的列表。

    (使用循環等DO,DOLIST,DOTIMES,LOOP,降低,MAPC,MAPL,MAPCAR,MAPLIST,MAPCAN,或MAPCON代替遞歸,當適用時構建體)

總結:這是非常天真的代碼性能差。

Common Lisp提供了這種內置:SET-DIFFERENCE應該做你想做的。

http://www.lispworks.com/documentation/HyperSpec/Body/f_set_di.htm#set-difference

+0

就像我剛纔提到的那樣,我是新來的聆聽者,應該期待這麼幼稚。這就是說,感謝分析,我將不得不看看SET-DIFFERENCE,然後用REST切換REMOVE。你會如何編寫這個函數?我發現潛入脣齒相依就像潛入大海。 – schellsan 2010-07-29 04:11:16

1

Common Lisp不支持tail-call optimization(根據標準),並且您可能會因內存不足而導致內存不足(取決於實現方式)。

+3

不,該標準不保證TCO的支持。然而,大多數實現都這樣。 – Svante 2010-07-27 09:51:56

+3

@Svante,標準沒有對TCO做任何說明。它不僅「不保證」,而且如果它在那裏,甚至不會考慮它。當實施可能提供TCO時,沒有考慮TCO的影響或限制。因此該標準忽略了TCO及其後果。 – 2010-07-27 11:21:10

1

我不會寫這個功能,監守,爲Rainer Joswig says,標準已經提供SET-DIFFERENCE。儘管如此,如果我必須提供的功能的實現,這是一個我會用:

(defun filter (a b) 
    (let ((table (make-hash-table))) 
    (map 'nil (lambda (e) (setf (gethash e table) t)) a) 
    (remove-if (lambda (e) (gethash e table)) b))) 

這樣做,這樣提供了一些優點,最重要的是,它僅穿越b一次;使用散列表來跟蹤a中的元素如果a很長可能會表現得更好。

此外,使用通用序列的功能,如MAPREMOVE-IF意味着這種功能可以用字符串和載體以及列表被使用,這是一個優點,甚至在標準SET-DIFFERENCE功能。這種方法的主要缺點是,如果您想用:TEST參數擴展函數,該參數允許用戶提供除默認EQL以外的相等謂詞,因爲CL哈希表僅適用於少量預定義的相等謂詞(準確地說是EQEQL,EQUALEQUALP)。

+0

啊,很好,謝謝。 – schellsan 2010-07-30 16:18:05

1
(defun filter (a b) 
    "Filters out all items in a from b" 
    (if (not (consp a)) b 
     (filter (rest a) (rest b)))) 
相關問題