list - 通过与 Common Lisp 中的 alist 进行比较来删除列表中的子列表

标签 list loops common-lisp remove-if

这很复杂,我希望有一个更简单的方法来做到这一点。

我正在将社交网站新生成的“建议连接”列表与“阻止的建议”列表进行比较。第一个列表看起来像这样:

((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被保留,因为阻止列表中没有相应的条目。

我真的希望有一种方法可以更干净地做到这一点。也许使用 removeremove-ifmapcar 和/或 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/

相关文章:

Python 集与列表

Java 按功能分组

javascript - 如果相同位置的项目相等,则比较数组项目(项目是数组)

lisp - 使用 asdf3 在 slime 中编译 defsystem 时出现无效的相对路径名错误

Lisp - 将所有元素增加一个数字

c - 通过递归函数打印链表的节点

javascript - AngularJS 显示数组中的列表

javascript - JS : Iterate over page & convert US Dollars to Rands

Python pandas 循环值以两列为条件

syntax-error - sbcl 非法函数调用