1
votes

I've been trying to map the nested values of a map within a vector into a vector of vectors without success.

The data I have is like this:

[{:country {:name "chile", :id 1},
  :subcountries [{:name "talca", :id 2}
                 {:name "concepcion", :id 3}
                 {:name "puerto montt", :id 4}]}
 {:country {:name "united states", :id 5},
  :subcountries [{:name "boston", :id 6}
                 {:name "texas", :id 7}]}]

While the code I've been playing with vaguely returns an approximation of what I'm trying to get as a result:

(map
 (fn [x]
   (let [{{id :id name :name} :country
          subcountries :subcountries} x]
     [id
      name
      (map (fn [y] (let [{yid :id yname :yname} y] [yid yname])))]))
 data)

The result I'm receiving with that is something pretty odd, since the vector I'd want to have is just a function:

([1 "chile" #function[clojure.core/map/fn--5862]]
 [5 "united states" #function[clojure.core/map/fn--5862]])

What am I doing wrong?

Expected output should be something like:

[[["chile" 1] ["talca" 2] ["concepcion" 3] ["puerto montt" 4]]
 [["united states" 5] ["boston" 6] ["texas" 7]]]
2
What is your desired output for shown sample of data?jas
Sorry, didn't add that, I do it ...Karol Karol
Really what I'm trying to do is to map data into a vector of option tags (clojure script) using the name as the inner text and the id as the value attribute.Karol Karol

2 Answers

4
votes

The reason you're seeing the function in your vector output is that your inner map wasn't applying the function to any data structure, so it was returning a transducer.

Here I've updated the inner map to map the function to the subcountries, which I assume was your intent. (There was also a tiny typo, you had yname :yname instead of yname :name)

(defn f [data]
  (mapv
   (fn [x]
     (let [{{id :id name :name} :country
            subcountries :subcountries} x]
       [id
        name
        (mapv (fn [y] (let [{yid :id yname :name} y] [yid yname])) subcountries)]))
   data))

Not sure if this is exactly your desired output, since you said "something like...". If not, let us know if you need more help getting it the rest of the way there.

> (f data)
[[1 "chile" [[2 "talca"] [3 "concepcion"] [4 "puerto montt"]]]
 [5 "united states" [[6 "boston"] [7 "texas"]]]]
3
votes

This might be a more "Clojurey" way to do it:

(defn countries->vecs [data]
  (let [->pair (juxt :name :id)
        map->pairs (fn [{:keys [country subcountries]}]
                     (apply vector (->pair country) 
                                   (map ->pair subcountries)))]
    (mapv map->pairs data)))