How can I group a list of lists by a given index in elisp? The lists represent tables, like org-tables, so each sublist represents a row, eg.
| a | 1 | 0 |
| b | 1 | 1 |
| c | 0 | 0 |
would be '((a 1 0) (b 1 1) (c 0 0)).
I want to be able to then group a given column by another column. So, for example, grouping the first column by the third, I would expect '((0 a c) (1 b)) since the third column of the first and third rows is 0.
I have tried the following code, but it make so many loops. Is there a grouping function in elisp or a better way?
;; group column1 by column2 in table
(defun group-by (col1 col2 table)
(let ((vals (cl-remove-duplicates ;find unique values to group by
(cl-loop for row in table
collect (nth col2 row)))))
(cl-loop for val in vals ;for each unique value
collect (cons val (cl-loop for row in table ;check each row for match
when (eq val (nth col2 row))
collect (nth col1 row))))))
(defvar tst-data '((a 1 0) (b 1 1) (c 0 0)))
(group-by 0 2 tst-data)
;; ((1 b)
;; (0 a c))
There happens to be a function on the ElispCookbook that can group elements of a list, called
group-by-eq. This function in-turn takes a function,f, that will be applied to each element ("row") of the list, and then group the list ("rows") by that value.Using that function, we can write a group by column function by passing it a function calling
nth:And your question asks for a double-grouping, but let's just group once:
Well, I thought there was a second grouping, but then it looks like you want to just select the nth element of each group, in this case the first element: