| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| I am starting now learning common lisp. here is a function which meant to return all elements found in list1 which dose not exists on list 2. The first version which aims to return a value returns nil while using the same approach but printing it dose shows the new values. >>(defun not-members (lst1 lst2) (let ((newlist nil)) (dolist (elm lst1) (if (null (member elm lst2)) (append newlist elm))) newlist)) NOT-MEMBERS >>(not-members '(d f g r t) '(a b c d e f g h i)) NIL >>(defun print-not-members (lst1 lst2) (let ((newlist nil)) (dolist (elm lst1) (if (null (member elm lst2)) (format t "~A" elm))) newlist)) PRINT-NOT-MEMBERS >>(print-not-members '(d f g r t) '(a b c d e f g h i)) RT NIL |
|
#2
| |||
| |||
| Tzury Bar Yochay wrote: > I am starting now learning common lisp. > here is a function which meant to return all elements found in list1 > which dose not exists on list 2. You mean set-difference? > > The first version which aims to return a value returns nil while using > the same approach but printing it dose shows the new values. > > > >>>(defun not-members (lst1 lst2) > > (let ((newlist nil)) > (dolist (elm lst1) > (if (null (member elm lst2)) > (append newlist elm))) > newlist)) Aside: append wants lists. Is elm always a list? (Meaning lst1 is always a list of lists.) Anyway... You have to (setf newlist (append newlist elm)), append is not destructive, it copies all but the last list so the result is fresh up front. nconc would be destructive, but you are starting with a nil value for newlist so you would still have to capture the first nconc. kt > > NOT-MEMBERS > >>>(not-members '(d f g r t) '(a b c d e f g h i)) > > > NIL > >>>(defun print-not-members (lst1 lst2) > > (let ((newlist nil)) > (dolist (elm lst1) > (if (null (member elm lst2)) > (format t "~A" elm))) > newlist)) > > PRINT-NOT-MEMBERS > >>>(print-not-members '(d f g r t) '(a b c d e f g h i)) > > RT > NIL -- http://www.theoryyalgebra.com/ "In the morning, hear the Way; in the evening, die content!" -- Confucius |
|
#3
| |||
| |||
| Thanks for quick response. > You mean set-difference? The idea is to write my own version of union which preserves the order of the elements in the original lists. e.g: > (new-union '(a b c) '(b a d)) (A B C D) > You have to (setf newlist (append newlist elm)), append is not > destructive, it copies all but the last list so the result is fresh up > front. ;; Got the point here is my working version ;-) (defun not-members (lst1 lst2) (let ((newlist ())) (dolist (elm lst1) (if (null (member elm lst2)) (setf newlist (append newlist (list elm))))) newlist)) |
|
#4
| |||
| |||
| On Jan 3, 6:15 pm, Tzury Bar Yochay <Afro.Syst...@gmail.com> wrote: > Thanks for quick response. > > > You mean set-difference? > > The idea is to write my own version of union which preserves the order > of the elements in the original lists. e.g: > > > (new-union '(a b c) '(b a d)) > > (A B C D) Something like this? ;; Unoptimized code fallowing (defun new-union (&rest args) (remove-duplicates (reduce #'append args) :from-end t)) (new-union '(a b c) '(b a d)) >(A B C D) (new-union '(a b c) '(b a d) '(d a)) >(A B C D) > > > You have to (setf newlist (append newlist elm)), append is not > > destructive, it copies all but the last list so the result is fresh up > > front. > > ;; Got the point here is my working version ;-) > > (defun not-members (lst1 lst2) > (let ((newlist ())) > (dolist (elm lst1) > (if (null (member elm lst2)) > (setf newlist (append newlist (list elm))))) > newlist)) |
|
#5
| |||
| |||
| On Jan 3, 5:51 pm, Tzury Bar Yochay <Afro.Syst...@gmail.com> wrote: > I am starting now learning common lisp. > here is a function which meant to return all elements found in list1 > which dose not exists on list 2. Try loop : (defun not-present (x1 x2) (loop for e in x1 when (not (member e x2)) collect e)) (not-present '(1 2 3 4 7 8 ) '( 3 4 5)) (1 2 7 8) > > The first version which aims to return a value returns nil while using > the same approach but printing it dose shows the new values. > > >>(defun not-members (lst1 lst2) > > (let ((newlist nil)) > (dolist (elm lst1) > (if (null (member elm lst2)) > (append newlist elm))) > newlist)) > > NOT-MEMBERS > > >>(not-members '(d f g r t) '(a b c d e f g h i)) > > NIL>>(defun print-not-members (lst1 lst2) > > (let ((newlist nil)) > (dolist (elm lst1) > (if (null (member elm lst2)) > (format t "~A" elm))) > newlist)) > > PRINT-NOT-MEMBERS>>(print-not-members '(d f g r t) '(a b c d e f g h i)) > > RT > NIL |
|
#6
| |||
| |||
| On Jan 3, 11:51*am, Tzury Bar Yochay <Afro.Syst...@gmail.com> wrote: > The first version which aims to return a value returns nil while using > the same approach but printing it dose shows the new values. > >>(defun not-members (lst1 lst2) > * * (let ((newlist nil)) > * * * * (dolist (elm lst1) > * * * * * * (if (null (member elm lst2)) > * * * * * * * * (append newlist elm))) > * * * * newlist)) There's a potential efficiency issue here, in that MEMBER may traverse the entirety of LST2 looking for ELM, and will do that for each element of LST1. If LST1 and LST2 are long, this could take a while. There are a few ways around this; the one that looks best suited to your needs, especially since you make no provision for using anything but MEMBER's default test of EQL, is to use a hash table to keep track of all the elements in one list and check the other list against it. This is a common strategy for doing "settish" things, but in portable Common Lisp it's only really easy if you want to use one of the four basic hash table equality tests (EQ, EQL, EQUAL and EQUALP). (defun not-members/ht (list1 list2) "Returns a list of all elements of LIST1 which are not present in LIST2." (let ((set2 (make-hash-table))) (loop :for elt :in list2 :do (setf (gethash elt set2) t)) (loop :for elt :in list1 :unless (gethash elt set2) :collect elt))) Also, you said elsewhere in the thread you were ultimately interested in doing a version of UNION that will preserve the order of elements. Also, LOOP with the COLLECT clause is very useful for this sort of thing. Cheers, Pillsy |
|
#7
| |||
| |||
| On Jan 3, 11:51 am, Tzury Bar Yochay <Afro.Syst...@gmail.com> wrote: > I am starting now learning common lisp. > here is a function which meant to return all elements found in list1 > which dose not exists on list 2. If you're really just beginning Lisp I believe you should be working on becoming comfortable with recursion, before considering iteration. IMO, LOOP is really for black belts who have already mastered the art of recursion. Here is some advice from Mark Tarver, author of Qi: http://groups.google.com/group/comp....01f946fdc2ecfe This is a recursive solution for NOT-MEMBER. > (defun not-member (l1 l2) (cond ((endp l1) nil) ((member (first l1) l2) (not-member (rest l1) l2)) (t (cons (first l1) (not-member (rest l1) l2))))) NOT-MEMBER > (setf lst1 '(1 2 3 4 5 6 7 8) lst2 '(2 4 6 8)) (2 4 6 8) > (not-member lst1 lst2) (1 3 5 7) agt |
|
#8
| |||
| |||
| viper-2 wrote: > On Jan 3, 11:51 am, Tzury Bar Yochay <Afro.Syst...@gmail.com> wrote: > >>I am starting now learning common lisp. >>here is a function which meant to return all elements found in list1 >>which dose not exists on list 2. > > > > If you're really just beginning Lisp I believe you should be working > on becoming comfortable with recursion, before considering iteration. Scheme is the dreamy idealistic language for crap like that, CL is for practical people trying to get work done and the first thing a Lisper needs to learn after how conses work is to use the right tool for the job and loop is the right tool for iteration which this example requires. Recursion is great fun and should be used only when a task cannot be completed on one element without the result of that task performed on subsequent elements. kt -- http://www.theoryyalgebra.com/ "In the morning, hear the Way; in the evening, die content!" -- Confucius |
|
#9
| |||
| |||
| On Jan 3, 11:15 am, Tzury Bar Yochay wrote: > The idea is to write my own version of union which preserves > the order of the elements in the original lists. > (setf newlist (append newlist (list elm))))) TBY, APPEND is very slow. To return the elements in order, all you have to do is (push elm newlist) and then when your function is finished adding elements to newlist, newlist will be exactly backwards, so you can just return (nreverse newlist). --Dan www.prairienet.org/~dsb/ |
|
#10
| |||
| |||
| Thank you all. Lisp Rocks! |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.