你有你的括號所有混亂的行動:
(defun stable-union (x y)
(cond
((null x) y)
((null y) x) ) END OF COND form - has no effect
(do ((i y (cdr i))
^^
(lst3 x (append lst3
(cond
((listp i)
( (null (member (car i) lst3))
^^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ called as a function
(cons (car i) nil) with two arguments
nil ))
^^
(t NEXT 3 forms have no effect
(null (member i lst3))
(cons i nil)
nil )))))
^^
((null (cdr i)) lst3)))
這裏是你的代碼,你可能想要它是與修正的括號,並增加了一些if
小號需要的地方:
(defun stable-union (x y)
(cond
((null x) y)
((null y) x)
(t
(do ((i y (cdr i))
(lst3 x (append lst3
(cond
((listp i)
(if (null (member (car i) lst3))
(cons (car i) nil)
nil))
(t
(if (null (member i lst3))
(cons i nil)
nil))))))
((null (cdr i)) lst3)))))
該代碼仍然存在問題。您的do
邏輯錯誤,如果它僅包含一個元素,則跳過y
中的第一個元素。無論是否需要,您始終致電append
。請注意,調用(append lst3 nil)
會使lst3
中的頂層cons單元副本完全不必要。
你這樣長的陳述通常放在do
正文中,而不是在do
的本地變量的更新表格中。
但是你可以使用的do
,在適當情況下更專門的表格。這裏很自然地使用dolist
。繼"wvxvw"'s lead on using hash-tables for membership testing,我們寫:
(defun stable-union (a b &aux (z (list nil)))
(let ((h (make-hash-table))
(p z))
(dolist (i a)
(unless (gethash i h)
(setf (cdr p) (list i) p (cdr p))
(setf (gethash i h) t)))
(dolist (i b (cdr z))
(unless (gethash i h)
(setf (cdr p) (list i) p (cdr p))
(setf (gethash i h) t)))))
使用的技術,我稱之爲「頭哨兵」(z
變量初始化前的單列表)允許代碼爲自上而下的列表建設一個偉大的簡化代價是分配一個額外的cons
單元。
是的,他留下了大部分。 'stable-union'是一個Xemacs庫函數,所以你可以查看它。它完全保留了原始列表的完整性,並且不要求任何一個列表都是唯一的,只是第一個列表中的任何成員都從第二個列表中刪除,並且二者的順序都被保留。其中一部分隱含在他給出的部分規範中,其餘部分在代碼中(即使它有點破碎)。 – itsbruce
你是對哈希表提供最快的解決方案,雖然:) – itsbruce