Is there an equivalent to the remove function that will
remove an element of a list (or just as well the nth element),
even if it is a list?
For example, I can do the following:
(remove 'a '(a b c)); and get (b c)
But if I try (remove '(a b) '(a b c)) ; nothing happens
If not I would welcome suggestion on the best
way to approach writing a function to remove the
nth element of a list.
Thanks,
Mark
"Mark" <················@ufl.edu> writes:
> Is there an equivalent to the remove function that will
> remove an element of a list (or just as well the nth element),
> even if it is a list?
>
> For example, I can do the following:
>
> (remove 'a '(a b c)); and get (b c)
>
> But if I try (remove '(a b) '(a b c)) ; nothing happens
>
> If not I would welcome suggestion on the best
> way to approach writing a function to remove the
> nth element of a list.
You are not asking the right question. REMOVE will remove a list.
But its default concept of what element to remove is based on the
TEST argument. By default, EQL is used, and the list you've offered
as arg1 is not EQL to the one you are removing.
For example
(setq x '(a b))
(remove x (list 'a x 'b)) => (a b)
But you can even do
(setq x '(a b))
(setq y (copy-list x))
(remove x (list 'a y 'b) :test #'equal)
if you want to use EQUAL as the identity test instead of EQL.
The thing you're showing an example of though doesn't do what your
english text asks for. If you want a function that removes all
elements in a given list, you want something like:
(defun remove-set (set list)
(remove-if #'(lambda (x) (member x set)) list)
(remove-set '(a b) '(a b c)) => (c)
I didn't take the time to test any of the above examples, so I hope
they really work like I said. Good luck.
Thanks for the reply.
Actually what I meant to type as the original
example was I wanted to do
(remove '(a b) ( (a b) (c d))
and it was in fact as Gary and you pointed out
the right :test that I was missing.
So this worked for me:
(remove '(a b) '((a b) (c d)) :test #'equalp)
Mark
Kent M Pitman <······@world.std.com> wrote in message
····················@world.std.com...
> "Mark" <················@ufl.edu> writes:
>
> > Is there an equivalent to the remove function that will
> > remove an element of a list (or just as well the nth element),
> > even if it is a list?
> >
> > For example, I can do the following:
> >
> > (remove 'a '(a b c)); and get (b c)
> >
> > But if I try (remove '(a b) '(a b c)) ; nothing happens
> >
> > If not I would welcome suggestion on the best
> > way to approach writing a function to remove the
> > nth element of a list.
>
> You are not asking the right question. REMOVE will remove a list.
> But its default concept of what element to remove is based on the
> TEST argument. By default, EQL is used, and the list you've offered
> as arg1 is not EQL to the one you are removing.
>
> For example
> (setq x '(a b))
> (remove x (list 'a x 'b)) => (a b)
>
> But you can even do
> (setq x '(a b))
> (setq y (copy-list x))
> (remove x (list 'a y 'b) :test #'equal)
> if you want to use EQUAL as the identity test instead of EQL.
>
> The thing you're showing an example of though doesn't do what your
> english text asks for. If you want a function that removes all
> elements in a given list, you want something like:
>
> (defun remove-set (set list)
> (remove-if #'(lambda (x) (member x set)) list)
> (remove-set '(a b) '(a b c)) => (c)
>
> I didn't take the time to test any of the above examples, so I hope
> they really work like I said. Good luck.
In article <············@nntp9.atl.mindspring.net>, "Mark" <················@ufl.edu> writes:
|> Is there an equivalent to the remove function that will
|> remove an element of a list (or just as well the nth element),
|> even if it is a list?
|>
|> For example, I can do the following:
|>
|> (remove 'a '(a b c)); and get (b c)
|>
|> But if I try (remove '(a b) '(a b c)) ; nothing happens
|>
|> If not I would welcome suggestion on the best
|> way to approach writing a function to remove the
|> nth element of a list.
|>
|> Thanks,
|>
|> Mark
|>
|>
Mark,
Remove will remove from a list, objects which match its first
argument. What your example is asking for is the removal of
any instances of the list '(a b) from the second list. The
second list, however, has three element: a, b and c.
Try:
(remove '(a b) '(a (a b) c) :test #'equalp)
=> (a c)
In this case the list '(a b) exists as an element of the list,
and will be removed.
You could get your original example to work as you expected
by using your own test, e.g:
(defun MyTest (list element) (member element list))
(remove '(a b) '(a b c) :test #'MyTest)
=> (c)
Here the test is that the element of the main list is
an element of the list you wish to remove.
A better approach in this case would be the use of set-difference
which will return elements of the first list that are not in the
second, i.e:
(set-difference '(a b c) '(a b))
=> (c)
As far as removing the nth element of a list, I would use
a function like:
(defun rem-nth (n list)
(remove-if #'identity '(1 2 3 4 5) :start n :end (1+ n)))
Where the list is indexed from 0.
Gary.
--
Gary Curtis <······@radagast.sogs.stsci.edu> wrote in message
·················@tomm.stsci.edu...
> In article <············@nntp9.atl.mindspring.net>, "Mark"
<················@ufl.edu> writes:
> |> If not I would welcome suggestion on the best
> |> way to approach writing a function to remove the
> |> nth element of a list.
> |>
> |> Thanks,
> |>
> |> Mark
> |>
> |>
>
> As far as removing the nth element of a list, I would use
> a function like:
>
> (defun rem-nth (n list)
> (remove-if #'identity '(1 2 3 4 5) :start n :end (1+ n)))
>
> Where the list is indexed from 0.
>
> Gary.
> --
How about:
(defun remove-nth(index list)
(remove (nth index list) list))
;;(remove-nth 3 '(0 1 2 3 4 5 6))
;;=>(0 1 2 4 5 6)
But aren't we just doing this fellow's homework for him?
(just guessing!)
coby
"coby" <·····@mercury.bc.ca> writes:
> But aren't we just doing this fellow's homework for him?
> (just guessing!)
Ha. That'll be the day, when someone actually has homework where the
correct answer is to use a convenient keyword argument to a sequence
function instead of code some stupid, clumsy recursive answer.
Kent M Pitman <······@world.std.com> wrote in message
····················@world.std.com...
> ······@radagast.sogs.stsci.edu (Gary Curtis) writes:
>
> > In article <··········@news.vphos.net>, "coby" <·····@mercury.bc.ca>
writes:
> > |> How about:
> > |> (defun remove-nth(index list)
> > |> (remove (nth index list) list))
>
> > Hmmm. But what about (remove-nth 3 '(1 2 1 2 1 2 1 2)) ???
> >
> > => (1 1 1 1)
>
> Try using also the :count argument to remove. You might have better luck.
Like:
(defun remove-nth(index list)
(remove (nth index list) list :count 1))
?
Still has a problem, eg:
(remove-nth 3 '(1 2 1 2 1 2 1 2))
==>(1 1 2 1 2 1 2)
It removes the first occurence of the third item! (maybe you were thinking
of another way to use :count?)
This seems to work better:
(defun remove-nth (index list)
(let ((new-list nil)
(counter 0))
(reverse (dolist (next list new-list)
(unless (= counter index)
(push (nth counter list) new-list))
(incf counter)))))
(it was so much simpler when it wasn't working! :-)
cb
"coby" <·····@mercury.bc.ca> writes:
> Still has a problem, eg:
>
> (remove-nth 3 '(1 2 1 2 1 2 1 2))
> ==>(1 1 2 1 2 1 2)
> It removes the first occurence of the third item! (maybe you were thinking
> of another way to use :count?)
Uh, right. No, I was just counting on it to do too much.
In article <··········@news.vphos.net>, coby <·····@mercury.bc.ca> wrote:
>This seems to work better:
>
>(defun remove-nth (index list)
> (let ((new-list nil)
> (counter 0))
> (reverse (dolist (next list new-list)
> (unless (= counter index)
> (push (nth counter list) new-list))
> (incf counter)))))
>
>(it was so much simpler when it wasn't working! :-)
This seems a bit simpler:
(defun remove-nth (index list)
(nconc (subseq list 0 index) (nthcdr (1+ index) list)))
--
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
Barry Margolin <······@bbnplanet.com> writes:
> This seems a bit simpler:
>
> (defun remove-nth (index list)
> (nconc (subseq list 0 index) (nthcdr (1+ index) list)))
Though it doesn't address the issue of index being out of bounds.
(min index (length list)) fixes it but means traversing the list twice,
if one cares about that.