I have the following map which I want to iterate:
(def db {:classname "com.mysql.jdbc.Driver" :subprotocol "mysql" :subname "//100.100.100.100:3306/clo" :username "usr" :password "pwd"})
I've tried the following, but rather than printing the key and value once, it repeatedly prints the key and values as various combinations:
(doseq [k (keys db) v (vals db)] (println (str k " " v)))
I came up with a solution, but Brian's (see below) are much more logical.
(let [k (keys db) v (vals db)] (do (println (apply str (interpose " " (interleave k v))))))
That's expected behavior. (doseq [x ... y ...])
will iterate over every item in y
for every item in x
.
Instead, you should iterate over the map itself once. (seq some-map)
will return a list of two-item vectors, one for each key/value pair in the map. (Really they're clojure.lang.MapEntry
, but behave like 2-item vectors.)
user> (seq {:foo 1 :bar 2}) ([:foo 1] [:bar 2])
doseq
can iterate over that seq just like any other. Like most functions in Clojure that work with collections, doseq
internally calls seq
on your collection before iterating over it. So you can simply do this:
user> (doseq [keyval db] (prn keyval)) [:subprotocol "mysql"] [:username "usr"] [:classname "com.mysql.jdbc.Driver"] [:subname "//100.100.100.100:3306/clo"] [:password "pwd"]
You can use key
and val
, or first
and second
, or nth
, or get
to get the keys and values out of these vectors.
user> (doseq [keyval db] (prn (key keyval) (val keyval))) :subprotocol "mysql" :username "usr" :classname "com.mysql.jdbc.Driver" :subname "//100.100.100.100:3306/clo" :password "pwd"
More concisely, you can use destructuring to bind each half of the map entries to some names that you can use inside the doseq
form. This is idiomatic:
user> (doseq [[k v] db] (prn k v)) :subprotocol "mysql" :username "usr" :classname "com.mysql.jdbc.Driver" :subname "//100.100.100.100:3306/clo" :password "pwd"
You can simply do
(map (fn [[k v]] (prn k) (prn v)) {:a 1 :b 2})
The result is:
:a 1 :b 2
Is this what you were looking for?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With