如何在 Clojure 中迭代映射键和值? [英] How to Iterate over Map Keys and Values in Clojure?

查看:18
本文介绍了如何在 Clojure 中迭代映射键和值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下要迭代的地图:

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))))))

推荐答案

这是预期的行为.(doseq [x ... y ...]) 将针对 x 中的每个项目迭代 y 中的每个项目.

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])

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"]

你可以使用keyval,或者firstsecond,或者nthget 以从这些向量中获取键和值.

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"

更简洁地说,您可以使用解构将地图条目的每一半绑定到一些您可以在 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"

这篇关于如何在 Clojure 中迭代映射键和值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆