loops - Removing sublists in a list by comparing them with an alist in Common Lisp -
this complicated, , i'm hoping there's simpler way it.
i'm comparing freshly generated list of "suggested connections" social networking site against "blocked suggestions" list. first list looks this:
((12 :mutuals 8 :ranking 8)(43 :mutuals 2 :mutual-groups (2) :ranking 4) ... )
the first value user id, , plist in cdr of each sublist "reasons" why person suggested.
the second list looks like:
((12 . 2) (3 . 4) (43 . 3) ...)
the car user id , cdr ranking had when "blocked" user's suggestions.
i want find way, each sublist in first list, compare against list of blocked suggestions. there 3 possible outcomes:
- there no corresponding entry => leave suggestion in list.
- there corresponding entry , ranking field 5 or more higher => leave suggestion in list , remove blocked suggestion index.
- there corresponding entry ranking same or within 5 => remove suggestion list of suggestions.
my current code uses loop
. best way me spell out literally possible.
(this in let
block in defun
. function (remove-suggestion)
own function modifies hash table.)
(let ((userid 10753) ; userid in program, 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 suggestion in suggestion-list sug-id = (car suggestion) sug-rank = (getf (cdr suggestion) :ranking) collect (loop (block-id . block-rank) in blocked-list until (= block-id sug-id) (if (/= block-id sug-id (return suggestion) (when (>= (- sug-rank block-rank) 5) (progn (remove-suggestion block-id userid :blocked t) (return suggestion))))))))
when evaluate in repl, get:
((12 :mutuals 8 :ranking 8)) (4 :mutuals 10 :ranking 10))
which right, since though user 12 blocked before, ranking went retained. user 43 removed because ranking had not gotten high enough. user 4 kept because there no corresponding entry in blocked list.
i'm hoping there way more cleanly. perhaps using combination of remove
, remove-if
, mapcar
, and/or lambda
?
i know store list in question defparameter
, use
(remove suggested-contact <location> :key #'car)
which did before, don't conceptually.
if made end, congrats!
ok, can 2 remove-if
s - 1 each list.
for first one:
(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) ...))
and second:
(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) ...))
Comments
Post a Comment