• Re: Collecting like-labelled sublists of a list

    From B. Pym@Nobody447095@here-nor-there.org to comp.lang.lisp on Thu Jun 26 15:52:46 2025
    From Newsgroup: comp.lang.lisp

    B. Pym wrote:

    Madhu wrote:

    (defun test (list)
    (loop for j in list
    for index = (first j)
    for k = (rest j)
    with indices = nil
    if (not (member index indices))
    do (pushnew index indices)
    and collect j into res
    else
    do (nconc (assoc index res) k) ; ASSOC instead of NTH
    finally (return res)))

    To be more precise (if that helps), I'm wondering if there's a way of
    doing this without having to build up a list of the indices (labels)
    and using membership/non-membership of this list as the test for
    whether we have encountered a new index or not.

    You can get by without building indices and just using ASSOC (which you cannot avoid):

    (defun cortez-group (list) ; Destroys LIST!
    (let (result)
    (dolist (el list)
    (let ((entry (assoc (car el) result)))
    (if entry
    (rplacd entry (nconc (cdr entry) (cdr el)))
    (push el result))))
    (nreverse (mapcar #'cdr result))))

    * (setq $a '((0 a b) (1 c d) (2 e f) (3 g h) (1 i j)
    (2 k l) (4 m n) (2 o p) (4 q r) (5 s t)))
    * (cortez-group $a)
    ((A B) (C D I J) (E F K L O P) (G H) (M N Q R) (S T))

    Gauche Scheme

    Non-destructive. (The way that association lists are handled
    is wonderfully dirty.)

    (define (c-group lst)
    (let ((result ()) (keys ()))
    (dolist (xs lst)
    (let* ((x (car xs)) (found (assoc x result)))
    (push! result
    (if found
    (append found (cdr xs))
    xs))
    (or (member x keys) (push! keys x))))
    (map (^k (cdr (assoc k result))) keys)))

    (c-group '((0 a b) (1 c d) (2 e f) (3 g h) (1 i j) (2 k l)
    (4 m n) (2 o p) (4 q r) (5 s t)))

    ===>
    ((s t) (m n q r) (g h) (e f k l o p) (c d i j) (a b))


    --- Synchronet 3.21d-Linux NewsLink 1.2