< Back to IRCAM Forum

Grouping by same first value

Hi all,
I have a list of lists where the lists always contain two values, like this one:

(2.0 329.62756)
(2.0 261.62555)
(2.0 97.99885)
(2.0 349.22824)
(2.84 329.62756)
(2.84 391.99542)
(2.943 195.99773)
(2.943 277.18265)
(3.047 293.66476)
(3.047 246.94165)
(3.683 195.99773)
(3.683 329.62756)
(3.683 349.22824)
(3.683 349.22824)
(4.118 130.81278)
(4.118 246.94165)
(4.118 261.62555)
(4.118 195.99773)

I’d need to group the lists in the list on the base of the first value of every list, so that the lists which contain the same first value are grouped together:

((2.0 329.62756)
(2.0 261.62555)
(2.0 97.99885)
(2.0 349.22824))
((2.84 329.62756)
(2.84 391.99542))
((2.943 195.99773)
(2.943 277.18265))
((3.047 293.66476)
(3.047 246.94165))
((3.683 195.99773)
(3.683 329.62756)
(3.683 349.22824)
(3.683 349.22824))
((4.118 130.81278)
(4.118 246.94165)
(4.118 261.62555)
(4.118 195.99773))

What is the lisp code or the patch that could do this work?
Thanks for your kind attention.
Best,
Francesco Vitale

Hi Francesco,

See the screenshot attached. I am not sure how to do this without the “remove nil” other than that this works.
Ciao!

Michele

Screen-Shot-2015-03-21-at-5.45.53-PM.png

Of course you can also use sort-list in lambda with the key argument “first” (as at the bottom of my patch) and then group all of the elements that have the same first atom. This way you would avoid the multiple iterations of the same list.

Hi Michele,
forgive me if I’m misunderstanding your suggestion, but your patch seems to be a more convoluted way to arrange the values in ascending order on the base of the first value of every sublist. This can be done more simply with a patch like the one shown here. If you take a closer look at my example in my first post, you can see that the problem does not regard sorting, but grouping… Grazie ancora per l’aiuto.
Best,
Francesco Vitale

1.png

Actually you are right, but if you take out the last “flat 1” and just get the out of the mapcar you will have the grouped sublists. To sort them in ascending order you have to add another passage.
Is that clear?

Dear Michele,
it works fine. The last passage was unnecessary. Many thanks for your enlightening solution.
All the best,
Francesco

2.png

Addendum (code)
Maybe this code will make the operation more efficient.
Use this code in a LISP object to get the groups and then use the result in a “group-list” object in OM to subdivide the list.
If speed of execution is not an issue you might just use the other patch.
(defun groups (lst)
(let ((allgrp
(let ((grp (loop for i on lst
for cnt from 1 to (- (length lst) 1)
when (not (= (caar i) (caadr i))) collect cnt))) ;collects count when a new first element is spotted
(append (list 0) (append grp (list (length lst))))))) ;prepend 0 and append list length to get first and last groups
(loop for g on allgrp
for c from 1 to (- (length allgrp) 1)
collect (abs (- (car g) (cadr g)))))); calculates differences between counts to get the groupings