-
-
Save bsless/6d820d84d2d145bf0958d89798710639 to your computer and use it in GitHub Desktop.
(defn map-or-vec? | |
[x] | |
(or (map? x) (vector? x))) | |
;;; https://www.reddit.com/r/Clojure/comments/7wl7nt/get_a_list_of_all_paths_in_a_nested_map/ | |
(defn paths | |
([m] | |
(paths [] [] m)) | |
([ps ks m] | |
(reduce-kv | |
(fn [ps k v] | |
(if (map-or-vec? v) | |
(paths ps (conj ks k) v) | |
(conj ps (conj ks k)))) | |
ps | |
m))) |
Interesting. What was your use-case?
As it happened, I was reading David Nolen's tutorial about Enlive - which uses often-complex nested maps to encapsulate scraped HTML. Without really delving into the ways to navigate to the leaf elements through Enlive, I wanted to see at a glance all paths to a leaf node, discover the paths that interest me (the leaf nodes are usually eye-grabbing at the REPL from being a path's last element) and filter for them, then retrieve the content - in this case a reddit page. From that a quick function can be made to read reddit articles at the repl. (I eventually realised the same can be done much more easily with Enlive's HTML screen scraping, without the need to provide specific paths, so I probably wouldn't have bothered had I read the rest of the tutorial :)
Still, It dawned upon me that path exploration can be useful, and can be done generically to any collection type by extending a few protocols. I'm sure there's a mature library somewhere doing the same, but it was fun to write.
Interesting problem - where one wants to know the structure (where all the values are stored), without knowing anything about a value other than it being a collection. I did something similar here, with a bit of usage documentation under Key Paths in the Readme.