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

Popular posts from this blog

html - Sizing a high-res image (~8MB) to display entirely in a small div (circular, diameter 100px) -

java - IntelliJ - No such instance method -

identifier - Is it possible for an html5 document to have two ids? -