Find a value in an association list

Discussion of Emacs Lisp
Post Reply
Beltxarga
Posts: 5
Joined: Fri Apr 04, 2014 7:03 am
Location: France

Find a value in an association list

Post by Beltxarga » Sun Jun 29, 2014 10:25 am

Dear all,

I was wondering how I could find a value in an association list recursively, even if this value is inside a vector. Let me give you an example. I have this list (response from the Discogs API), let's call it discogs

Code: Select all

((resp (version . "2.0")
       (release
        (data_quality . "Correct")
        (tracklist . [... ... ...])
        (master_id . 18609)
        (resource_url . "http://api.discogs.com/releases/798045")
        (formats . [...])
        (artists . [...])
        (uri . "http://www.discogs.com/Photek-Natural-Born-Killa-EP/release/798045")
        (companies . [])
        (notes . "...")
        (country . "UK")
        (title . "Natural Born Killa EP") ...)
       (status . t)))
At the moment I have a function which can find any value as long as it is in a nested list:

Code: Select all

(defun tree-assoc (key tree)
  (when (consp tree)
    (destructuring-bind (x . y)  tree
      (if (eql x key) tree
        (or (tree-assoc key x) (tree-assoc key y))))))
So for example,

Code: Select all

(cdr (tree-assoc 'title discogs))
will find the value "Natural Born Killa EP". Fine.

However, the name of the artist is inside a vector, in the cons cell (artists . [...]). This vector contains another nested list, like this:

Code: Select all

[((id . 417) (resource_url . "http://api.discogs.com/artists/417") (role . "") (tracks . "") (anv . "") (name . "Photek") (join . ""))]
So I'm looking for a way to modify tree-assoc so the recursion won't be broken by a vector. How could I do that?

Thanks,

Beltxarga
Last edited by Beltxarga on Tue Jul 01, 2014 1:48 pm, edited 1 time in total.

edgar-rft
Posts: 226
Joined: Fri Aug 06, 2010 6:34 am
Location: Germany

Re: Find a value in an association list

Post by edgar-rft » Mon Jun 30, 2014 8:32 am

Code: Select all

(defun recursive-assoc (key data)
  (cond ((consp data) <recursive-code-for-handling-nonempty-lists>)
        ((vectorp data) <recursive-code-for-handling-vectors>)
        (t (error "not a nonempty list or vector: %s" data))))

Beltxarga
Posts: 5
Joined: Fri Apr 04, 2014 7:03 am
Location: France

Re: Find a value in an association list

Post by Beltxarga » Tue Jul 01, 2014 1:48 pm

edgar-rft wrote:

Code: Select all

(defun recursive-assoc (key data)
  (cond ((consp data) <recursive-code-for-handling-nonempty-lists>)
        ((vectorp data) <recursive-code-for-handling-vectors>)
        (t (error "not a nonempty list or vector: %s" data))))
Thank you edgar-rift! It was very useful. I came up with this:

Code: Select all

(defun btx/discogs-get-value (data key)
  (cond
   ((consp data) (destructuring-bind (x . y) data
		   (if (eql x key) y
		     (or (btx/discogs-get-value x key)
			      (btx/discogs-get-value y key)))))
   ((vectorp data) (btx/discogs-get-value (elt data 0) key))))
And it seems to work! I would very much like your opinion about the way I'm getting details about the release, like the artist name, title... If you look at the tree, you can find the artist name by going through a 'artists' index, itself associated with a vector, which contains a 'name' index, like this :

Code: Select all

   (artists .
	    [((id . 417)
	      (resource_url . "http://api.discogs.com/artists/417")
	      (role . "")
	      (tracks . "")
	      (anv . "")
	      (name . "Photek")
	      (join . ""))])
So the value associated with that 'name' index is the name of the artist. So I simply came up with this:

Code: Select all

(defun btx/discogs-get-artist-name (release)
  (let ((release_info (btx/discogs-query release)))
    (btx/discogs-get-value (btx/discogs-get-value release_info 'artists) 'name)))
I think it is a simple but inelegant way to walk the tree, to call btx/discogs-get-value multiple times recursively, even if I don't have to call it more than 2 times to access most of the release details. BTW, btx/discogs-query-release is for getting the tree that you saw above, of course. My idea was to allow multiple parameters in btx/discogs-get-value, but the recursion make it quite complicated for me...

Thank you,

Beltxarga

PS : I can't seem to achieve a correct indentation for my code in the forum... Is it normal?!

Post Reply