Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[N]TRUNCATE-LIST ?

82 views
Skip to first unread message

Philip Lijnzaad

unread,
Feb 11, 2000, 3:00:00 AM2/11/00
to
Dear all,

after some browsing in the HyperSpec, I couldn't find a function that yields,
as a list, the first N elts of the list passed as an argument, sort of the
opposites of [N]BUTLAST. I was thinking of something along the following lines:

(defun ntruncate-list (list n)
"destructive version of TRUNCATE-LIST"
(cond ((zerop n) nil)
((>= n (length list)) list)
(t (rplacd (nthcdr (1- n) list) nil) list)))

(defun truncate-list (list n)
"makes a truncated copy of LIST of at most length N. Only the structure of
LIST is copied, not the elemements. Fails for circular or improper lists"
(ntruncate-list (append list nil) n))

Does such a function exist, and if so, what is it called, and if not, why not
(because it seems like a logical thing to have). Thanks for any info,

Philip
--
Not getting what you want is sometimes a wonderful stroke of luck.
-----------------------------------------------------------------------------
Philip Lijnzaad, lijn...@ebi.ac.uk | European Bioinformatics Institute,rm A2-24
+44 (0)1223 49 4639 | Wellcome Trust Genome Campus, Hinxton
+44 (0)1223 49 4468 (fax) | Cambridgeshire CB10 1SD, GREAT BRITAIN
PGP fingerprint: E1 03 BF 80 94 61 B6 FC 50 3D 1F 64 40 75 FB 53

Michael Kappert

unread,
Feb 11, 2000, 3:00:00 AM2/11/00
to

Philip Lijnzaad wrote:
>
> Dear all,
>
> after some browsing in the HyperSpec, I couldn't find a function that yields,
> as a list, the first N elts of the list passed as an argument, sort of the
> opposites of [N]BUTLAST. I was thinking of something along the following lines:

You need only to complement the index wrt. list length:

(defun ntruncate-list (list n)
(nbutlast list (- (length list) n)))

Regards,
Michael.

--
Michael Kappert
Fraunhofer IITB
Fraunhoferstr. 1 Phone: +49(0)721/6091-477
D-76131 Karlsruhe, Germany EMail: k...@iitb.fhg.de

Philip Lijnzaad

unread,
Feb 11, 2000, 3:00:00 AM2/11/00
to
On Fri, 11 Feb 2000 14:24:37 +0100,
"Michael" == Michael Kappert <k...@iitb.fhg.de> writes:

Michael> Philip Lijnzaad wrote:

PL> I couldn't find a function that yields,
PL> as a list, the first N elts of the list passed as an argument, sort of the
PL> opposites of [N]BUTLAST. I was thinking of something along the following lines:

Michael> (defun ntruncate-list (list n)
Michael> (nbutlast list (- (length list) n)))

Ah, of course, that's considerably easier. Still, is there a standard
function for doing this?

Incidentally, I'm curious where the convention of an 'N' prefix for
destructive functions comes from. I suppose it all started with NCONC, but
there too, the N doesn't seem to be particularly mnemonic (non-consing?
nasty?) Any veteran care to comment?

Pierre R. Mai

unread,
Feb 11, 2000, 3:00:00 AM2/11/00
to
Michael Kappert <k...@iitb.fhg.de> writes:

> Philip Lijnzaad wrote:
> >
> > Dear all,
> >

> > after some browsing in the HyperSpec, I couldn't find a function
> > that yields, as a list, the first N elts of the list passed as an
> > argument, sort of the opposites of [N]BUTLAST. I was thinking of


> > something along the following lines:
>

> You need only to complement the index wrt. list length:
>
> (defun ntruncate-list (list n)

> (nbutlast list (- (length list) n)))

If you are going to write an ntruncate function, then this approach is
needlessly sub-optimal, because it will have to traverse the whole
list first (to get length), before traversing the front part again to
modify/copy the head. Philipp's version had the same problem. The
following is my stab at writing ntruncate-list, which ignores out of
bounds indices and does the right thing w.r.t. to them (analogous to
nbutlast).

(defun ntruncate-list (list n)
"Destructive version of truncate-list that returns (at most) the n
first elements of list as a list."
(when (> n 0)
(do ((i (1- n) (1- i))
(rest list (cdr rest)))
((or (zerop i) (null (cdr rest)))
(setf (cdr rest) nil)
list))))

(defun truncate-list (list n)
"Non-destructively returns (at most) the n first elements of list as
a list."
(when (> n 0)
(do* ((i (1- n) (1- i))
(rest (cdr list) (cdr rest))
(result (cons (car list) nil))
(result-rest result (cdr result-rest)))
((or (zerop i) (null rest))
result)
(setf (cdr result-rest) (cons (car rest) nil)))))

Regs, Pierre.

--
Pierre Mai <pm...@acm.org> PGP and GPG keys at your nearest Keyserver
"One smaller motivation which, in part, stems from altruism is Microsoft-
bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]

Philip Lijnzaad

unread,
Feb 11, 2000, 3:00:00 AM2/11/00
to
On 11 Feb 2000 16:32:27 +0100,
"Pierre" == Pierre R Mai <pm...@acm.org> writes:

Pierre> needlessly sub-optimal, because it will have to traverse the whole
Pierre> list first (to get length), before traversing the front part again to
Pierre> modify/copy the head. Philipp's version had the same problem.

I thought of that, that's why I wrote

>> > argument, sort of the opposites of [N]BUTLAST. I was thinking of
>> > something along the following lines:

to get the idea across, not as a production quality code ... Thanks anyway
for the code!

Andrew Cooke

unread,
Feb 11, 2000, 3:00:00 AM2/11/00
to
In article <38A40D95...@iitb.fhg.de>,

Michael Kappert <k...@iitb.fhg.de> wrote:
> (defun ntruncate-list (list n)
> (nbutlast list (- (length list) n)))

This is inefficient, isn't it? It takes O((length list)) rather than
O(n).

(For a non-destructive version, loop with collect seems as good as
anything).

Andrew
http://www.andrewcooke.free-online.co.uk


Sent via Deja.com http://www.deja.com/
Before you buy.

Robert Munyer

unread,
Feb 11, 2000, 3:00:00 AM2/11/00
to
In article <u7hfffd...@o2-3.ebi.ac.uk>,
Philip Lijnzaad <lijn...@ebi.ac.uk> wrote:

> after some browsing in the HyperSpec, I couldn't find a function
> that yields, as a list, the first N elts of the list passed as

> an argument, sort of the opposites of [N]BUTLAST.
[...]


> Does such a function exist, and if so, what is it called, and if
> not, why not (because it seems like a logical thing to have).

For the non-destructive version, just use (SUBSEQ LIST 0 N).

For the destructive version, use (SETF (NTHCDR N LIST) NIL).

-- Robert Munyer <mun...@mcs.com>

Erik Naggum

unread,
Feb 11, 2000, 3:00:00 AM2/11/00
to
* Philip Lijnzaad <lijn...@ebi.ac.uk>

| after some browsing in the HyperSpec, I couldn't find a function that yields,
| as a list, the first N elts of the list passed as an argument, sort of the
| opposites of [N]BUTLAST.

have you looked at SUBSEQ for the non-destructive version? or a fairly
plain SETF of NTHCDR for a destructive version? if you have to check for
the length, use NTHCDR, see if you get a cons cell, then SETF its CDR.
there's absolutely _no_ need to check the length of the list, which,
incidentally, may be circular, so use LIST-LENGTH instead of LENGTH if
you think you really have to.

#:Erik

0 new messages