# Emacs lisp list grouping

**URL:** <https://forum.systemcrafters.net/t/emacs-lisp-list-grouping/544>\
**Category:** Emacs\
**Tags:** emacs-lisp, lisp\
**Created:** [April 4, 2024, 12:19pm UTC](https://forum.systemcrafters.net/t/emacs-lisp-list-grouping/544 "2024-04-04T12:19:45Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![tusharhero](https://avatars.discourse-cdn.com/v4/letter/t/e99b99/32.png) [@tusharhero](https://forum.systemcrafters.net/u/tusharhero)\
**Post date:** [April 4, 2024, 12:19pm UTC](https://forum.systemcrafters.net/t/emacs-lisp-list-grouping/544/1 "2024-04-04T12:19:45Z")

</div>

Let say I have this list.

```
'((name (tag1))
  (name2 (tag2))
  (name3 (tag1))
  (name4 (tag3))
  (name5 (tag2 tag1)))

```

How do I get this?

```
'((tag1 (name name3 name5))
  (tag2 (name2 name5))
  (tag3 (name4)))

```

This is for my blog: [Tagged view (experimental)](https://tusharhero.codeberg.page/tags.html)

---

<div class="post-metadata">

**Author:** ![barocio](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.systemcrafters.net/barocio/32/384_2.png) [@barocio](https://forum.systemcrafters.net/u/barocio)\
**Post date:** [April 4, 2024, 3:54pm UTC](https://forum.systemcrafters.net/t/emacs-lisp-list-grouping/544/2 "2024-04-04T15:54:16Z")

</div>

I think this could do the trick:

```lisp
(progn
  (setq articles '((name (tag1))
		   (name2 (tag2))
		   (name3 (tag1))
		   (name4 (tag3))
		   (name5 (tag2 tag1)))
	the-tags '()
	tags-list '()
	tags-listp '())
  (mapcar (lambda (entry)
	    (let* ((title (car entry))
		   (tags (cadr entry)))
	      (message "Processing %S" entry)
	      (message " title %S" title)
	      (message " tags %S" tags)
	      (mapcar (lambda (tag)
			(add-to-list 'the-tags tag :append)
			(let ((tag-list (plist-get tags-listp tag)))
			  (message " tag-list(%S) %S" tag tags-listp)
			  (setq tags-listp (plist-put tags-listp tag (append `(,title) tag-list)))))
		      tags)))
	  articles)
  the-tags
  (mapcar
   (lambda (tag)
     (add-to-list 'tags-list `(,tag ,(plist-get tags-listp tag))))
   the-tags)
  tags-list)

```

Most surely it is not the most efficient way to code this, but it works.

---

<div class="post-metadata">

**Author:** ![alphapapa](https://avatars.discourse-cdn.com/v4/letter/a/5f9b8f/32.png) [@alphapapa](https://forum.systemcrafters.net/u/alphapapa)\
**Post date:** [April 5, 2024, 12:27am UTC](https://forum.systemcrafters.net/t/emacs-lisp-list-grouping/544/3 "2024-04-05T00:27:40Z")

</div>

This is what I wrote Taxy for: [GitHub - alphapapa/taxy.el: Programmable taxonomical hierarchies for arbitrary objects](https://github.com/alphapapa/taxy.el)

Here’s an example of doing it with your sample code:

```lisp
(let* ((articles '((name (tag1))
                   (name2 (tag2))
                   (name3 (tag1))
                   (name4 (tag3))
                   (name5 (tag2 tag1))))
       (tags (delete-dups
              (flatten-list (mapcar #'cadr articles))))
       (taxy (make-taxy
              :name "Blog articles"
              :taxys (mapcar (lambda (tag)
                               (make-taxy :name (symbol-name tag)
                                          :predicate (lambda (article)
                                                       (member tag (cadr article)))
                                          :then #'identity))
                             tags))))
  (setf taxy (thread-last taxy
                          taxy-emptied
                          (taxy-fill articles))
        (taxy-items taxy) nil)
  (taxy-plain taxy))

```

That produces:

```lisp
("Blog articles"
 (("tag1" ((name5 (tag2 tag1))
           (name3 (tag1))
           (name (tag1))))
  ("tag2" ((name5 (tag2 tag1))
           (name2 (tag2))))
  ("tag3" ((name4 (tag3))))))

```

---

<div class="post-metadata">

**Author:** ![cryptk](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.systemcrafters.net/cryptk/32/67_2.png) [@cryptk](https://forum.systemcrafters.net/u/cryptk)\
**Post date:** [April 5, 2024, 12:59am UTC](https://forum.systemcrafters.net/t/emacs-lisp-list-grouping/544/4 "2024-04-05T00:59:32Z")

</div>

My attempt:

```auto
(let* ((data '((name (tag1))
               (name2 (tag2))
               (name3 (tag1))
               (name4 (tag3))
               (name5 (tag2 tag1)))))
  (mapcar (lambda (tag)
            `(,tag ,(delete nil
                            (mapcar (lambda (item)
                                      (when (member tag (cadr item))
                                        (car item)))
                                    data))))
          (delete-dups (flatten-tree (mapcar #'cdr data)))))

```

---

<div class="post-metadata">

**Author:** ![tusharhero](https://avatars.discourse-cdn.com/v4/letter/t/e99b99/32.png) [@tusharhero](https://forum.systemcrafters.net/u/tusharhero)\
**Post date:** [April 11, 2024, 11:00pm UTC](https://forum.systemcrafters.net/t/emacs-lisp-list-grouping/544/5 "2024-04-11T23:00:02Z")

</div>

This made sense to me so I adopted it.

---

<div class="post-metadata">

**Author:** ![armindarvish](https://yyz1.discourse-cdn.com/flex029/user_avatar/forum.systemcrafters.net/armindarvish/32/464_2.png) [@armindarvish](https://forum.systemcrafters.net/u/armindarvish)\
**Post date:** [April 20, 2024, 12:10pm UTC](https://forum.systemcrafters.net/t/emacs-lisp-list-grouping/544/6 "2024-04-20T12:10:57Z")

</div>

I think you can use a hashtable or plist for the second list (the one you want to make) then you don’t have to worry about duplicate keys. and will have one less mapcar!

with plist:

```auto
(let ((l '((name (tag1))
          (name2 (tag2))
          (name3 (tag1))
          (name4 (tag3))
          (name5 (tag2 tag1))))
      (pl (list)))
(mapcar (lambda (item) 
          (mapcar (lambda (tag) 
                    (setq pl (plist-put pl tag (append (list (car item)) (plist-get pl tag)))))
                  (cadr item)))
        l)
pl
)

```

but personally I’d prefer a hashtable:

```auto
(let ((data '((name (tag1))
          (name2 (tag2))
          (name3 (tag1))
          (name4 (tag3))
          (name5 (tag2 tag1))))
      (table (make-hash-table :test 'equal)))
(mapcar (lambda (item) 
          (mapcar (lambda (tag) 
                    (puthash tag (append (list (car item)) (gethash tag table))
                             table)) 
                  (cadr item)))
        data)
table
)

```

---

<div class="post-metadata">

**Author:** ![tusharhero](https://avatars.discourse-cdn.com/v4/letter/t/e99b99/32.png) [@tusharhero](https://forum.systemcrafters.net/u/tusharhero)\
**Post date:** [April 20, 2024, 1:01pm UTC](https://forum.systemcrafters.net/t/emacs-lisp-list-grouping/544/7 "2024-04-20T13:01:40Z")

</div>

> I think you can use a hashtable or plist for the second list (the one you  
> want to make) then you don’t have to worry about duplicate keys. and will  
> have one less mapcar!

I will make sure to take a look at it, the current solutions works fine  
but it has 2 mapcars as you say.
