2017-06-05 70 views
0

我遇到此功能的問題two-similar-p列表之間的兩個常見元素

(defun two-similar-p (list1 list2) 
    (mapcar 
    (lambda (e) 
    (mapcar 
     (lambda (e1) 
     (if (equal e e1) t)) 
     list2)) 
    list1)) 

但不正確的使用mapcar,因爲這個函數返回TNIL一個新的列表,但我只需要返回一個true或false。

ex。

(two-similar-p '(2 1 3) '(1 2 3)) 
==> ((NIL T NIL) (T NIL NIL) (NIL NIL T)) 

我想用遞歸來比較不同的元素,但我不知道該怎麼做。 我的功能需要像這樣工作:

(two-similar-p '(1 2 3) '(1 4 5)) ; ==> nil 

(two-similar-p '(1 2 5) '(1 4 5)) ; ==> t 

(two-similar-p '(1 2 6) '(6 4 2)) ; ==> t 

有什麼建議嗎?

+0

爲什麼第一個例子返回'nil'? – melpomene

+0

ops,對不起,第一個例子返回nil,因爲它們沒有至少兩個相等的元素。 –

+0

你需要使用'mapcar'嗎? – sds

回答

1

最簡單的「關閉的,現成的」解決方案是檢查intersection含有至少兩種元素:

(defun two-similar-p (l1 l2) 
    (consp (cdr (intersection l1 l2 :test #'equal)))) 

稍微少OTS解決方案是使用hash tables

(defun two-similar-p (l1 l2) 
    (let ((h1 (make-hash-table :test 'equal)) 
     (common 0)) 
    (dolist (x l1) 
     (setf (gethash x h1) t)) 
    (dolist (x l2) 
     (when (gethash x h1) 
     (incf common)) 
     (when (>= common 2) 
     (return t))))) 

第二種方法的優點是它的複雜性是O(len(l1) + len(l2)), 而mapcar方法將是O(len(l1) * len(l2))

該標準沒有指定intersectionfriends的複雜度,但大多數實現都在這裏好好照顧他們的用戶(IOW,複雜度將是線性的,而不是二次的)。

+0

非常感謝你!我正在使用第一個解決方案和所有的工作 –

+0

@ GabrieleBisogno:不客氣! – sds

相關問題