fukamachi / assoc-utils

Utilities for manipulating association lists.
25 stars 1 forks source link

Function to retrieve nested values #11

Open justjoheinz opened 6 days ago

justjoheinz commented 6 days ago

As you already took inspiration from cl-hash-util - what about implementing the (hash-get obj '("user" "friends" 0 "name")) function to retrieve a chain of values.

I implemented that in a simple manner without lots of checking and couldn't come up with a suitable name yet.

(defun alist-get (alist &rest keys)
  "Recursively find KEYs in ALIST."
  (loop :for key :in keys
        :do (if (typep key (and 'fixnum 'unsigned-byte))
                (setq alist (nth key alist))
                (setq alist (aget alist key))))
  alist)

Given an alist like :

((:VERSION . "0.6")
 (:GENERATOR . "openstreetmap-cgimap 2.0.1 (1992 spike-08.openstreetmap.org)")
 (:COPYRIGHT . "OpenStreetMap and contributors")
 (:ATTRIBUTION . "http://www.openstreetmap.org/copyright")
 (:LICENSE . "http://opendatacommons.org/licenses/odbl/1-0/")
 (:ELEMENTS
  ((:TYPE . "node") (:ID . 1) (:LAT . 42.79572) (:LON . 13.569003)
   (:TIMESTAMP . "2024-09-13T11:52:01Z") (:VERSION . 39)
   (:CHANGESET . 156568263) (:USER . "SomeoneElse_Revert") (:UID . 1778799)
   (:TAGS (:|COMMUNICATION:MICROWAVE| . "yes") (:|COMMUNICATION:RADIO| . "fm")
    (:DESCRIPTION . "Radio Subasio") (:FREQUENCY . "105.5 MHz")
    (:MAN--MADE . "mast") (:NAME . "Monte Piselli - San Giacomo")
    (:NOTE . "This is the very first node on OpenStreetMap.")
    (:|TOWER:CONSTRUCTION| . "lattice") (:|TOWER:TYPE| . "communication")))))

one can do:

 (alist-get * :elements 0 :tags :note)
"This is the very first node on OpenStreetMap."
fukamachi commented 1 day ago

I ever thought that, but I wasn't sure if it was useful since it's easily achieved by cl:reduce like this:

(defvar *alist* '((:a . ((:b . ((:c . :d)))))))

(reduce #'aget '(:a :b :c) :initial-value *alist*)
;=> :D
justjoheinz commented 1 day ago

But you can't get the nth element for example. the reduce example is nice though.

fukamachi commented 9 hours ago

True. I noticed it by your example. I'm waiting for coming up a good function name.