2011-12-03 52 views
0

我遇到了此lisp函數的問題。我想創建一個接收兩個列表的函數,並驗證第一個列表中的元素(全部)是否出現在第二個列表中,如果發生這種情況,它將返回True。Lisp - Lisp的元素出現在其他列表中

目前,我有以下代碼:

(defun ocorre-listas (l1 l2) 
(dolist (elem1 l1) 
    (dolist (elem2 l2) 
     (if (equal elem1 elem2) 
      t)))) 

它不工作,符合市場預期。我應該試着做一個簡單的遞歸嗎?我真的沒有得到如何我可以遍歷這兩個列表尋找相同的元素。

,我決定嘗試沒有dolists。這就是我現在所擁有的,它仍然不起作用。

(defun ocorre-listas (l1 l2) 
(cond ((null l1) nil) 
     ((null l2) nil) 
     ((if (/= (first l1)(first l2)) (ocorre-listas l1 (rest l2)))) 
     (t (if (= (first l1) (first l2)) (ocorre-listas (rest l1)(rest l2)))))) 

我收到一個警告,說「t」是一個未定義的函數。另外,我嘗試的每個例子都返回null。我究竟做錯了什麼 ?

+1

正確縮進你的代碼。看到表單被正確嵌套。 –

回答

1

在第二代碼段,如果第一列表是空的,則其所有的元素都在第二個。

你不需要ifs因爲你是內cond

測試之後,如果列表是空的,你只需要測試,如果第一個列表的第一個元素是在第二個和再次使用沒有此元素的第一個列表調用函數

1

爲了能夠在同一時間在兩個列表中的工作,關鍵是可能開始遞歸之前的列表進行排序。那麼它應該是比較的第一個元素,並遞歸地應用相同的功能列表的其餘部分,與一些汽車的一個簡單的事情/ CDR魔法加當然...

+0

列表已經排序......最難的部分是獲得CAR/CDR的魔法發生;) –

1

,而不是試圖在一個做的一切功能,請考慮將其分成兩個(或更多)功能,例如

  • 一個採用一個數和第二列表,並測試的數量是否出現在列表中
  • 另一種迭代的數量在第一列表中,併爲每一個測試(使用第一功能)是否出現在第二個列表中。

除了DOLIST,可以考慮使用MAPCARFIND-IF(假設它們被允許在此分配。)​​

2

因此,您需要檢查l1的every元素是否爲l2的member。這些都是Common Lisp標準庫中的函數,所以如果您允許使用它們,您可以使用它們構建一個簡單的解決方案。

1

見Common Lisp的subsetp 謂詞及其實施:

CL-USER> (subsetp '(1 2 3) '(1 2 3 4) 
T 
0

雖然有很多方法可以做到這一點,我會建議使用一個哈希表,以避免O(n^2)複雜。使用散列表,你可以達到O(n)的複雜性。

這裏是聯合功能

(defun my-union (a b) 
    (let ((h (make-hash-table :test #'equal))) 
    (mapcar (lambda (x) (setf (gethash x h) x)) a) 
    (mapcan (lambda (x) (when (gethash x h) (list x))) b))) 

這裏是boths列表

(defun same-elements (a b) 
    (apply #'= (mapcar #'length (list (my-union a b) a b)))) 

這裏的相同元素的功能測試是確保ab一個子集(你問什麼功能)

(defun subset (a b) 
    (same-elements (my-union a b) a)) 
+0

注意:我的函數假定列表不包含重複項 – protist