我有以下想要迭代的地图:
(def db {:classname "com.mysql.jdbc.Driver"
:subprotocol "mysql"
:subname "//100.100.100.100:3306/clo"
:username "usr" :password "pwd"})
Run Code Online (Sandbox Code Playgroud)
我尝试过以下操作,但不是打印键和值一次,而是重复打印键和值作为各种组合:
(doseq [k (keys db)
v (vals db)]
(println (str k " " v)))
Run Code Online (Sandbox Code Playgroud)
我想出了一个解决方案,但Brian(见下文)更符合逻辑.
(let [k (keys db) v (vals db)]
(do (println (apply str (interpose " " (interleave k v))))))
Run Code Online (Sandbox Code Playgroud)
Bri*_*per 92
这是预期的行为. (doseq [x ... y ...])将遍历每个项目中y的每个项目x.
相反,您应该迭代地图本身一次. (seq some-map)将返回一个两项向量的列表,一个用于映射中的每个键/值对.(真的是他们clojure.lang.MapEntry,但表现得像2项向量.)
user> (seq {:foo 1 :bar 2})
([:foo 1] [:bar 2])
Run Code Online (Sandbox Code Playgroud)
doseq可以像其他任何一样遍历那个seq.像Clojure中使用集合的大多数函数一样,在迭代之前doseq内部调用seq集合.所以你可以这样做:
user> (doseq [keyval db] (prn keyval))
[:subprotocol "mysql"]
[:username "usr"]
[:classname "com.mysql.jdbc.Driver"]
[:subname "//100.100.100.100:3306/clo"]
[:password "pwd"]
Run Code Online (Sandbox Code Playgroud)
您可以使用key和val,或first和second,或nth,或get从这些向量中获取键和值.
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"
Run Code Online (Sandbox Code Playgroud)
更简洁地说,您可以使用解构将每个映射条目的一半绑定到您可以在doseq表单中使用的某些名称.这是惯用的:
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"
Run Code Online (Sandbox Code Playgroud)
Mri*_*abh 19
你可以干脆做
(map (fn [[k v]] (prn k) (prn v)) {:a 1 :b 2})
结果是:
:a
1
:b
2
Run Code Online (Sandbox Code Playgroud)
这是你在找什么?
只是Brian回答的一小段内容:
您的原始版本也可以编写如下。
(doseq [[k v] (map vector (keys db) (vals db))]
(println (str k " " v)))
Run Code Online (Sandbox Code Playgroud)
在这种情况下,这显然是愚蠢的。但总的来说,这也适用于不相关的输入序列,这些输入序列并非源于同一图。