如何遍历Clojure中的映射键和值? [英] How to Iterate over Map Keys and Values in Clojure?

查看:69
本文介绍了如何遍历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 ...])将遍历 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])

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 ,或先使用 second ,或 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"

更简洁地说,您可以使用解构将映射条目的每半绑定到一些名称,这些名称可以在 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天全站免登陆