Welcome! Please see the About page for a little more info on how this works.

0 votes
in Collections by

Hi,
From a nested map, I'd like to build a map that saves all key - value pairs whose keys satisfy some conditions.
I'm using babashka.
Tried some different solutions, but I'm not able to retrieve all pairs.

The first one, using (I think) a more functional approach j-h5.

    #!/usr/bin/env bb
    
    ; expected output: {"k23" {"k231" "v231"} "k24" "v24"}
 (def j {"k1" "v1" "k2" {"k21" "v21" "k22" "v22" "k23" {"k231" "v231"} "k24" "v24"} "k3" "v3"})
(println j)

(println "Doing j-h5")
(defn j-h5 [s mymap]
  (let [first-k (first (first s))
        first-v (second (first s)) ]
    (cond 
      (empty? s) nil
      (or (= "k23" first-k) (= "k24" first-k))
      (do 
        (assoc mymap first-k first-v)
        (when (and ( map? first-v) (seq first-v))
            (println  (str "doing recursion1 when k:" first-k "  and v:" first-v))
            (recur first-v mymap))
        )
      (map? first-v)
            (do 
              (println  (str "doing recursion2 when k:" first-k "  and v:" first-v))
              (recur first-v mymap))
      :else (recur (rest s) mymap) 
      )))

(j-h5 j {})
; mymap defined outside of function   
(println "Doing j-h1")
(def  mymap {})
(defn j-h1 [s]
  (let [first-k (first (first s))
        first-v (second (first s)) ]
    (cond 
      (empty? s) mymap
      (or (= "k23" first-k) (= "k24" first-k))
      (do 
        (assoc mymap first-k first-v)
        (when (and ( map? first-v) (seq first-v))
            (println  (str "doing recursion1 when k:" first-k "  and v:" first-v))
            (recur first-v))
        )
      (map? first-v)
            (do 
              (println  (str "doing recursion2 when k:" first-k "  and v:" first-v))
              (recur first-v))
      :else (recur (rest s)) 
      )))

(j-h1 j)

How can this be fixed?

1 Answer

0 votes
by
 
Best answer

I managed to find a solution for my question.
It's hard to begin in a functional way after so many years thinking in an imperative way.

(defn j-h5 [s mymap]
  (let [first-k (first (first s))
        first-v (second (first s)) ]
    (cond 
      (empty? s) mymap
      (or (= "k23" first-k) (= "k24" first-k))
        (recur (rest s) (assoc mymap first-k first-v))
      (map? first-v) (recur first-v mymap)
      :else (recur (rest s) mymap) 
      )))

(println (j-h5 j {}))
by
Nice!

I tried coming up with a tree-seq-variant that might be interesting:


(defn j-h5 [s]
  (into {}
        (keep (fn [value]
                (when (map? value)
                  (select-keys value ["k23" "k24"]))))
        (tree-seq map? vals s)))
...