당신은 당신의 괄호에게있어 모든 뒤죽박죽 업 : 당신은 아마 수를 의도 한대로
(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)))
여기 수정 parenthesization로, 코드 그리고 필요한 경우 일부 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