From: ······@gmail.com
Subject: Grouping list elements
Date: 
Message-ID: <1129240038.784097.245850@g47g2000cwa.googlegroups.com>
At one point I recall reading in a Lisp book about a function which
would
take a list as input and break it up into a list of n-element sublists
plus
the remainder, e.g.

  (foo 3 '(1 2 3 4 5 6 7))  =>  ((1 2 3) (4 5 6) (7))

The trouble is I can't remember its name, or whether it was standard or
a
user-defined function.  I looked through the HyperSpec and c.l.l for
all the
synonyms of "group", "partition", etc I could think of, but found
nothing.
Does anyone know what I'm thinking of?

From: ········@gmail.com
Subject: Re: Grouping list elements
Date: 
Message-ID: <1129273829.799955.232170@g44g2000cwa.googlegroups.com>
I guess it was group from Graham's On Lisp.
From: Barry Margolin
Subject: Re: Grouping list elements
Date: 
Message-ID: <barmar-CB5DC4.00441114102005@comcast.dca.giganews.com>
In article <························@g47g2000cwa.googlegroups.com>,
 ······@gmail.com wrote:

> At one point I recall reading in a Lisp book about a function which
> would
> take a list as input and break it up into a list of n-element sublists
> plus
> the remainder, e.g.
> 
>   (foo 3 '(1 2 3 4 5 6 7))  =>  ((1 2 3) (4 5 6) (7))
> 
> The trouble is I can't remember its name, or whether it was standard or
> a
> user-defined function.  I looked through the HyperSpec and c.l.l for
> all the
> synonyms of "group", "partition", etc I could think of, but found
> nothing.
> Does anyone know what I'm thinking of?

It's not a standard Common Lisp function, and I can't think of any other 
well-known Lisp dialects that are likely to have this built-in.  It 
doesn't seem like a common idiom that needs to be predefined in the 
language, it seems more like the kind of thing that would be assigned as 
a homework problem in a beginning class.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: ······@gmail.com
Subject: Re: Grouping list elements
Date: 
Message-ID: <1129269106.678134.262150@g44g2000cwa.googlegroups.com>
Barry Margolin teithant i thiw hin:

> It's not a standard Common Lisp function, and I can't think of any
> other well-known Lisp dialects that are likely to have this
> built-in.  It doesn't seem like a common idiom that needs to be
> predefined in the language, it seems more like the kind of thing
> that would be assigned as a homework problem in a beginning class.

Well, I'm mainly interested in the case where n = 2; I'm turning a
user-supplied list of symbols into a bunch of key-value pairs to use
for a macro.  I just read something similar the other day and couldn't
remember the context in which it was described.

-- 
J "bad line wrapping courtesy of Google" W
From: Tayssir John Gabbour
Subject: Re: Grouping list elements
Date: 
Message-ID: <1129269559.555360.167120@z14g2000cwz.googlegroups.com>
······@gmail.com wrote:
> Barry Margolin teithant i thiw hin:
> > It's not a standard Common Lisp function, and I can't think of any
> > other well-known Lisp dialects that are likely to have this
> > built-in.  It doesn't seem like a common idiom that needs to be
> > predefined in the language, it seems more like the kind of thing
> > that would be assigned as a homework problem in a beginning class.
>
> Well, I'm mainly interested in the case where n = 2; I'm turning a
> user-supplied list of symbols into a bunch of key-value pairs to use
> for a macro.  I just read something similar the other day and couldn't
> remember the context in which it was described.

If I understand correctly, I think that's often done by the following
idiom:

(loop for (i j) on ... by #'cddr
      ...)


Tayssir
From: justinhj
Subject: Re: Grouping list elements
Date: 
Message-ID: <1129272146.858713.316120@g49g2000cwa.googlegroups.com>
; (break-n 3 '(1 2 3 4 5 6 7))  =>  ((1 2 3) (4 5 6) (7))

; break up a list into n parts
(defun break-n(n lst)
  (break-n-lst n lst (length lst)))

; break up a list of length len into parts of length n and a remainder
(defun break-n-lst(n lst len)
  (cond
    ((>= n len)
     (list lst))
    ((< n len)
     (cons
      (loop for x from 0 to (- n 1) collect (nth x lst))
      (break-n-lst n (nthcdr n lst) (- len n))))))
From: Pascal Bourguignon
Subject: Re: Grouping list elements
Date: 
Message-ID: <87u0fkvh2c.fsf@thalassa.informatimago.com>
······@gmail.com writes:

> At one point I recall reading in a Lisp book about a function which
> would
> take a list as input and break it up into a list of n-element sublists
> plus
> the remainder, e.g.
>
>   (foo 3 '(1 2 3 4 5 6 7))  =>  ((1 2 3) (4 5 6) (7))
>
> The trouble is I can't remember its name, or whether it was standard or
> a
> user-defined function.  I looked through the HyperSpec and c.l.l for
> all the
> synonyms of "group", "partition", etc I could think of, but found
> nothing.
> Does anyone know what I'm thinking of?

split ?

(defun split (n list)
  (labels ((at-most (l n c)
             (if (or (null l) (zerop c)) (- n c) (at-most (cdr l) n (1- c)))))
    (loop :for s :on list :by (lambda (l) (nthcdr n l))
          :collect (subseq s 0 (at-most s n n)))))

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
From: Alan Crowe
Subject: Re: Grouping list elements
Date: 
Message-ID: <86oe5so2gg.fsf@cawtech.freeserve.co.uk>
······@gmail.com writes:
> At one point I recall reading in a Lisp book about a function which
> would
> take a list as input and break it up into a list of n-element sublists
> plus
> the remainder, e.g.
> 
>   (foo 3 '(1 2 3 4 5 6 7))  =>  ((1 2 3) (4 5 6) (7))
> 
> The trouble is I can't remember its name, or whether it was standard or
> a
> user-defined function.  I looked through the HyperSpec and c.l.l for
> all the
> synonyms of "group", "partition", etc I could think of, but found
> nothing.
> Does anyone know what I'm thinking of?

Stealing nthcdr from Justin and subseq from Pascal, I get

* (defun group (n list)
    (if (not (endp (nthcdr n list)))
        (cons (subseq list 0 n)
              (group n (nthcdr n list)))
      (list list)))

(group 3 '(1 2 3 4 5 6 7)) => ((1 2 3) (4 5 6) (7))

Alan Crowe
Edinburgh
Scotland
From: GP lisper
Subject: Re: Grouping list elements
Date: 
Message-ID: <1129287783.bd94f9e05d6f90384508fe62b9213e55@teranews>
On 14 Oct 2005 10:46:55 +0100, <····@cawtech.freeserve.co.uk> wrote:
>
>
> ······@gmail.com writes:
>> At one point I recall reading in a Lisp book about a function which
>> would
>> take a list as input and break it up into a list of n-element sublists
>> plus
>> the remainder, e.g.
>> 
>>   (foo 3 '(1 2 3 4 5 6 7))  =>  ((1 2 3) (4 5 6) (7))
>> 
>> The trouble is I can't remember its name, or whether it was standard or
>> a
>> user-defined function.  I looked through the HyperSpec and c.l.l for
>> all the
>> synonyms of "group", "partition", etc I could think of, but found
>> nothing.
>> Does anyone know what I'm thinking of?
>
> Stealing nthcdr from Justin and subseq from Pascal, I get
>
> * (defun group (n list)
>     (if (not (endp (nthcdr n list)))
>         (cons (subseq list 0 n)
>               (group n (nthcdr n list)))
>       (list list)))
>
> (group 3 '(1 2 3 4 5 6 7)) => ((1 2 3) (4 5 6) (7))
>
> Alan Crowe
> Edinburgh
> Scotland


-- 
If you don't like LOOP, how do you feel about DOLIST ?
From: Alan Crowe
Subject: Re: Grouping list elements
Date: 
Message-ID: <86psq89hbe.fsf@cawtech.freeserve.co.uk>
GP lisper <········@CloudDancer.com> writes:
> On 14 Oct 2005 10:46:55 +0100, <····@cawtech.freeserve.co.uk> wrote:
> > * (defun group (n list)
> >     (if (not (endp (nthcdr n list)))
> >         (cons (subseq list 0 n)
> >               (group n (nthcdr n list)))
> >       (list list)))
>
> If you don't like LOOP, how do you feel about DOLIST ?

I'm not that hot a Lisp programmer. An early draft for this
code had

(defun first-few (n list)
  (loop repeat n
        for x in list
        collect x))

instead of just using (subseq list 0 n). Embarrassing.

If you have slick LOOP code, share!

Alan Crowe
Edinburgh
Scotland
From: justinhj
Subject: Re: Grouping list elements
Date: 
Message-ID: <1129313572.964336.17000@g47g2000cwa.googlegroups.com>
Alan Crowe wrote:
> GP lisper <········@CloudDancer.com> writes:
> > On 14 Oct 2005 10:46:55 +0100, <····@cawtech.freeserve.co.uk> wrote:
> > > * (defun group (n list)
> > >     (if (not (endp (nthcdr n list)))
> > >         (cons (subseq list 0 n)
> > >               (group n (nthcdr n list)))
> > >       (list list)))
> >
> > If you don't like LOOP, how do you feel about DOLIST ?
>
> I'm not that hot a Lisp programmer. An early draft for this
> code had
>
> (defun first-few (n list)
>   (loop repeat n
>         for x in list
>         collect x))
>
> instead of just using (subseq list 0 n). Embarrassing.
>
> If you have slick LOOP code, share!
>
> Alan Crowe
> Edinburgh
> Scotland

subseq! that's just what I need to get my card game dealing code down
in size. sweet
From: drewc
Subject: Re: Grouping list elements
Date: 
Message-ID: <B7W3f.198635$tl2.3975@pd7tw3no>
Alan Crowe wrote:
> GP lisper <········@CloudDancer.com> writes:
> 
>>On 14 Oct 2005 10:46:55 +0100, <····@cawtech.freeserve.co.uk> wrote:
>>
>>>* (defun group (n list)
>>>    (if (not (endp (nthcdr n list)))
>>>        (cons (subseq list 0 n)
>>>              (group n (nthcdr n list)))
>>>      (list list)))
>>
>>If you don't like LOOP, how do you feel about DOLIST ?
> 
> 
> I'm not that hot a Lisp programmer. An early draft for this
> code had
> 
> (defun first-few (n list)
>   (loop repeat n
>         for x in list
>         collect x))
> 
> instead of just using (subseq list 0 n). Embarrassing.

Actually, in this case it may not be a bad idea, because by using LOOP 
you can avoid the explicit check for the out of bounds error. Take the 
following LOOPs:

(defun split-list (n list)
   (loop for cons on list
         by #'(lambda (x) (nthcdr n x))
         if (< 0 n)
         collect (loop for atom in cons
                       repeat n
                       collect atom)
         else return nil))

CL-USER> (split-list 0 (list 1 2 3 4 5 6 7 8))
NIL
CL-USER> (split-list 1 (list 1 2 3 4 5 6 7 8))
((1) (2) (3) (4) (5) (6) (7) (8))
CL-USER> (split-list 3 (list 1 2 3 4 5 6 7 8))
((1 2 3) (4 5 6) (7 8))
CL-USER> (split-list 40000 (list 1 2 3 4 5 6 7 8))
((1 2 3 4 5 6 7 8))
CL-USER> (split-list 40000 (list 1 2 3 4 5 6 7 8))
((1 2 3 4 5 6 7 8))


> If you have slick LOOP code, share!

I use loop for this sort of thing all the time. I find it reads as a 
clear solution to the problem without cluttering my code with bounds 
checks, and i don't have to think as hard about it versus a recursive 
solution. Plus, i just get a kick out of loop... it's a lot of fun :)

-- 
Drew Crampsie
drewc at tech dot coop
  "... the most advanced use of lisp in the field of bass lure sales"
	-- Xach on #lisp
From: Alain Picard
Subject: Re: Grouping list elements
Date: 
Message-ID: <877jcgo254.fsf@memetrics.com>
······@gmail.com writes:

> At one point I recall reading in a Lisp book about a function which
> would
> take a list as input and break it up into a list of n-element sublists
> plus
> the remainder, e.g.
>
>   (foo 3 '(1 2 3 4 5 6 7))  =>  ((1 2 3) (4 5 6) (7))
>
> The trouble is I can't remember its name, or whether it was standard or

Graham has some functions like that in On Lisp.  Called group
and group-by.

And unlike Barry, I've actually found use for those in production code...

                                      --ap