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-ifs - 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