问题描述
我有以下的地图,我想迭代:
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)))
,但Brian's(见下文)更合乎逻辑。
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))))))
推荐答案
这是预期的行为。 (doseq [x ... y ...])
将迭代 y
中的每个项目 x
。
That's expected behavior. (doseq [x ... y ...])
will iterate over every item in y
for every item in x
.
而是应该遍历地图本身一次。 (seq some-map)
将返回两个项目向量的列表,其中一个用于地图中的每个键/值对。 (真的他们 clojure.lang.MapEntry
,但表现得像2项目的向量。)
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])
b $ b
doseq
可以像任何其他一样迭代该seq。像Clojure中使用集合的大多数函数一样, doseq
在迭代之前在集合中内部调用 seq
。所以你可以这样做:
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"]
您可以使用键
和 val
或
和秒
或 nth
或 get
获取这些向量中的键和值。
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"
b $ b
更简洁地说,你可以使用解构来将每一半的映射条目绑定到一些可以在 doseq
中使用的名称。这是惯用的:
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"
这篇关于如何迭代映射键和值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!