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, ········@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
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: ···@iitb.fhg.de
On Fri, 11 Feb 2000 14:24:37 +0100,
"Michael" == Michael Kappert <···@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?
Philip
--
Not getting what you want is sometimes a wonderful stroke of luck.
-----------------------------------------------------------------------------
Philip Lijnzaad, ········@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 <···@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 <····@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]
On 11 Feb 2000 16:32:27 +0100,
"Pierre" == Pierre R Mai <····@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!
Philip
--
Not getting what you want is sometimes a wonderful stroke of luck.
-----------------------------------------------------------------------------
Philip Lijnzaad, ········@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
In article <·················@iitb.fhg.de>,
Michael Kappert <···@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.
In article <··············@o2-3.ebi.ac.uk>,
Philip Lijnzaad <········@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 <······@mcs.com>
* Philip Lijnzaad <········@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