Find Value of Specific Key in Nested Map

后端 未结 4 708
一向
一向 2021-02-08 09:40

In Clojure, how can I find the value of a key that may be deep in a nested map structure? For example:

(def m {:a {:b \"b\"
            :c \"c\"
            :d {         


        
4条回答
  •  故里飘歌
    2021-02-08 10:31

    Clojure offers tree-seq to do a depth-first traversal of any value. This will simplify the logic needed to find your nested key:

    (defn find-nested
      [m k]
      (->> (tree-seq map? vals m)
           (filter map?)
           (some k)))
    
    (find-nested {:a {:b {:c 1}, :d 2}} :c)
    ;; => 1
    

    Also, finding all matches becomes a matter of replacing some with keep:

    (defn find-all-nested
      [m k]
      (->> (tree-seq map? vals m)
           (filter map?)
           (keep k)))
    
    (find-all-nested {:a {:b {:c 1}, :c 2}} :c)
    ;; => [2 1]
    

    Note that maps with nil values might require some special treatment.


    Update: If you look at the code above, you can see that k can actually be a function which offers a lot more possibilities:

    • to find a string key:

      (find-nested m #(get % "k"))
      
    • to find multiple keys:

      (find-nested m #(some % [:a :b]))
      
    • to find only positive values in maps of integers:

      (find-nested m #(when (some-> % :k pos?) (:k %)))
      

提交回复
热议问题