这很复杂,我希望有一个更简单的方法来做到这一点。
我正在将社交网站新生成的“建议连接”列表与“阻止的建议”列表进行比较。第一个列表看起来像这样:
((12 :mutuals 8 :ranking 8)(43 :mutuals 2 :mutual-groups (2) :ranking 4) ... )
第一个值是用户 ID,每个子列表的 cdr 中的 plist 本质上是建议该人的“原因”。
第二个列表如下所示:
((12 . 2) (3 . 4) (43 . 3) ...)
汽车是用户 ID,cdr 是他们被“阻止”用户建议时的排名。
我想找到一种方法,对于第一个列表中的每个子列表,将其与阻止的建议列表进行比较。存在三种可能的结果:
- 不会有相应的条目 => 将建议保留在列表中。
- 存在相应的条目,并且排名字段高于 5 分 => 将建议保留在列表中,并从其索引中删除被阻止的建议。
- 有相应的条目,但排名相同或在 5 以内 => 从建议列表中删除该建议。
我当前执行此操作的代码使用LOOP
。这是我尽可能按字面意思拼写出来的最佳方式。
(目前位于 LET
block 中,但最终将位于 defun
中。函数 (remove-suggestion)
是我的修改哈希表的自己的函数。)
(let ((userid 10753) ; my userid in this program, for example
(suggestion-list '((12 :mutuals 8 :ranking 8)(43 :mutuals 2 :mutual-groups (2) :ranking 4) (4 :mutuals 10 :ranking 10)))
(blocked-list '((12 . 2) (3 . 4) (43 . 3)))
(remove nil
(loop for suggestion in suggestion-list
for sug-id = (car suggestion)
for sug-rank = (getf (cdr suggestion) :ranking)
collect
(loop for (block-id . block-rank) in blocked-list
until (= block-id sug-id)
finally
(if (/= block-id sug-id (return suggestion)
(when (>= (- sug-rank block-rank) 5)
(progn
(remove-suggestion block-id userid :blocked t)
(return suggestion))))))))
当我在 REPL 中评估这一点时,我得到:
((12 :mutuals 8 :ranking 8)) (4 :mutuals 10 :ranking 10))
这是完全正确的,因为即使用户 12 之前被屏蔽,但他们的排名上升了,所以他们被保留了。用户 43 因排名不够高而被删除。用户4被保留,因为阻止列表中没有相应的条目。
我真的希望有一种方法可以更干净地做到这一点。也许使用 remove
、remove-if
、mapcar
和/或 lambda
的某种组合?
我知道我可以使用 defparameter
存储有问题的列表,然后使用
(remove suggested-contact <location> :key #'car)
这是我之前所做的,但从概念上讲我不太喜欢它。
如果你坚持到了最后,恭喜你!
最佳答案
好的,您可以使用 2 个 remove-if
来做到这一点 - 每个列表 1 个。
对于第一个:
(remove-if (lambda (e)
(let ((blocked (assoc (first e)
'((12 . 2) (3 . 4) (43 . 3) ...)))
(and blocked (< (cdr blocked) 5))))
'((12 :mutuals 8 :ranking 8)
(43 :mutuals 2 :mutual-groups (2) :ranking 4)
...))
第二个:
(remove-if (lambda (e)
(and (member (car e)
'((12 :mutuals 8 :ranking 8)
(43 :mutuals 2 :mutual-groups (2) :ranking 4)
...)
:key 'first)
(>= (cdr e) 5))
'((12 . 2) (3 . 4) (43 . 3) ...))
关于list - 通过与 Common Lisp 中的 alist 进行比较来删除列表中的子列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21488240/