From: Mark
Subject: remove a list from a list
Date: 
Message-ID: <7rog15$a1l$1@nntp9.atl.mindspring.net>
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

From: Kent M Pitman
Subject: Re: remove a list from a list
Date: 
Message-ID: <sfwd7vkvyv3.fsf@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.
From: Mark
Subject: Re: remove a list from a list
Date: 
Message-ID: <7rpk1b$6el$1@nntp1.atl.mindspring.net>
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.
From: Gary Curtis
Subject: Re: remove a list from a list
Date: 
Message-ID: <7rom42$i5p$2@tomm.stsci.edu>
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.
--
From: coby
Subject: Re: remove a list from a list
Date: 
Message-ID: <37dffc22_2@news.vphos.net>
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
From: Kent M Pitman
Subject: Re: remove a list from a list
Date: 
Message-ID: <sfwogf35w3l.fsf@world.std.com>
"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.
From: Gary Curtis
Subject: Re: remove a list from a list
Date: 
Message-ID: <7rtj0e$i5p$3@tomm.stsci.edu>
In article <··········@news.vphos.net>, "coby" <·····@mercury.bc.ca> writes:
|> 
|> 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
|> 
|> 
|> 
|> 


Hmmm. But what about (remove-nth 3 '(1 2 1 2 1 2 1 2)) ???

=> (1 1 1 1)

Gary.
--
From: Kent M Pitman
Subject: Re: remove a list from a list
Date: 
Message-ID: <sfwyae5ed1y.fsf@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.
From: coby
Subject: Re: remove a list from a list
Date: 
Message-ID: <37e27146_2@news.vphos.net>
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
From: Kent M Pitman
Subject: Re: remove a list from a list
Date: 
Message-ID: <sfwwvtp8ntg.fsf@world.std.com>
"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.
From: Barry Margolin
Subject: Re: remove a list from a list
Date: 
Message-ID: <KnvE3.115$zE6.6051@burlma1-snr2>
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.
From: Kent M Pitman
Subject: Re: remove a list from a list
Date: 
Message-ID: <sfwzoylz0jm.fsf@world.std.com>
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.