From: Andreas Thiele
Subject: Lisp Idiomatic/Tool Function
Date: 
Message-ID: <dfmuak$38h$02$1@news.t-online.com>
Hi All,

I'd like to combine adjacent equal items in a list to sublists. Thus I wrote
a tiny tool function which works and offers some flexibility.

I am not sure, if I'm just reinventing the wheel. Perhaps there is some
idiomatic or more idomatic way to accomplish this in Lisp I am not aware.

My solution offers the following:

Grouping items which are eq:
CL-USER 146 > (group '(1 1 1 2 2 2 1 1 3 3 3 4))
((1 1 1) (2 2 2) (1 1) (3 3 3) 4)

Grouping items who are eq to an on key:
CL-USER 147 > (group '(1 1 1 2 2 2 1 1 3 3 3 4) :on 1)
((1 1 1) 2 2 2 (1 1) 3 3 3 4)

Grouping items who are eq to some element in the on key:
CL-USER 148 > (group '(1 1 1 2 2 2 1 1 3 3 3 4) :on '(1 2))
((1 1 1) (2 2 2) (1 1) 3 3 3 4)

Grouping items who are eq to some element in the on key and applying a
combiner function on the sublists:
CL-USER 149 > (group '(1 1 1 2 2 2 1 1 3 3 3 4) :on '(1 2) :combiner 'car)
(1 2 1 3 3 3 4)

Grouping with a key:
CL-USER 151 > (group '((:a 1) (:a 2) (:b 3)) :key 'car)
(((:A 1) (:A 2)) (:B 3))

A more complex combiner:
CL-USER 157 > (group '((:a 1) (:a 2) (:b 3)) :key 'car :combiner #'(lambda
(col) (list :a (apply '+ (mapcar 'second col)))))
((:A 3) (:B 3))

Here is the function:

(defun group (lst &key (test 'eq) (key 'identity) on (combiner 'identity))
  (let* ((previous-item (car lst))
         (collector     (list previous-item))
         (result        nil)
         (testf (if on
                  (if (consp on)
                    (lambda (x y) (loop for c in on
                                        when (and (funcall test x c)
                                                  (funcall test y c)) return
t
                                        finally return nil))
                    (lambda (x y) (and (funcall test x on) (funcall test y
on))))
                  test)))
    (flet ((combine ()
             (let ((c (nreverse collector)))
               (if (cdr c)
                 (push (funcall combiner c) result)
                 (push (car c) result)))))
      (dolist (item (cdr lst))
        (if (funcall testf (funcall key item) (funcall key previous-item))
          (push item collector)
          (progn
            (combine)
            (setf collector (list item))))
        (setf previous-item item))
      (when collector (combine))
      (nreverse result))))

Any suggestions, hints, pointers?

Andreas

From: Sam Steingold
Subject: Re: Lisp Idiomatic/Tool Function
Date: 
Message-ID: <ufysg27n5.fsf@gnu.org>
> * Andreas Thiele <······@abfcnz.pbz> [2005-09-07 16:43:25 +0200]:
>
> I'd like to combine adjacent equal items in a list to sublists. Thus I
> wrote a tiny tool function which works and offers some flexibility.

see CLOCC/CLLIB/lisp.lisp:nsplit-list et al

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.palestinefacts.org/> <http://www.dhimmi.com/>
<http://www.mideasttruth.com/> <http://www.camera.org>
Small languages require big programs, large languages enable small programs.
From: Andreas Thiele
Subject: Re: Lisp Idiomatic/Tool Function
Date: 
Message-ID: <dfpbn5$j1t$00$1@news.t-online.com>
"Sam Steingold" <···@gnu.org> schrieb im Newsbeitrag ··················@gnu.org...
> ...
> see CLOCC/CLLIB/lisp.lisp:nsplit-list et al
> ...

Thanks for your libraries - very helpful.

Andreas
From: Edi Weitz
Subject: Re: Lisp Idiomatic/Tool Function
Date: 
Message-ID: <ud5njd8a4.fsf@agharta.de>
On Thu, 8 Sep 2005 14:44:21 +0200, "Andreas Thiele" <······@nospam.com> wrote:

> Thanks for your libraries - very helpful.

Hi Andreas!

As I know that you're (also) using Lisp commercially: Note that
relevant parts of CLOCC are under the GPL so before you use CLOCC code
in your programs you should check the legal implications first.

Cheers,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Andreas Thiele
Subject: Re: Lisp Idiomatic/Tool Function
Date: 
Message-ID: <dfsute$jbr$03$1@news.t-online.com>
"Edi Weitz" <········@agharta.de> schrieb im Newsbeitrag ··················@agharta.de...
> ...
> As I know that you're (also) using Lisp commercially: Note that
> relevant parts of CLOCC are under the GPL so before you use CLOCC code
> in your programs you should check the legal implications first.
> ...

Indeed a reason why I sometimes re-invent the wheel :)
Thanks for the hint.

Andreas