簡體   English   中英

如何迭代 Clojure 中的 Map 鍵和值?

[英]How to Iterate over Map Keys and Values in Clojure?

我有以下要迭代的 map:

(def db {:classname "com.mysql.jdbc.Driver" 
         :subprotocol "mysql" 
         :subname "//100.100.100.100:3306/clo" 
         :username "usr" :password "pwd"})

我嘗試了以下方法,但不是一次打印鍵和值,而是將鍵和值重復打印為各種組合:

(doseq [k (keys db) 
        v (vals db)] 
  (println (str k " " v)))

我想出了一個解決方案,但布賴恩的(見下文)更合乎邏輯。

(let [k (keys db) v (vals db)] 
  (do (println (apply str (interpose " " (interleave k v))))))

這是預期的行為。 (doseq [x... y...])將為x中的每個項目迭代y中的每個項目。

相反,您應該遍歷 map 本身一次。 (seq some-map)將返回一個包含兩項向量的列表,一個用於 map 中的每個鍵/值對。 (實際上它們是clojure.lang.MapEntry ,但表現得像 2 項向量。)

user> (seq {:foo 1 :bar 2})
([:foo 1] [:bar 2])

doseq可以像其他序列一樣迭代該序列。 與 Clojure 中與 collections 一起使用的大多數函數一樣, 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"]

您可以使用keyval ,或firstsecond ,或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"

更簡潔地說,您可以使用解構將 map 條目的每一半綁定到您可以在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"

你可以簡單地做

(map (fn [[kv]] (prn k) (prn v)) {:a 1:b 2})

結果是:

:a
1
:b
2

這是你要找的嗎?

只是對布賴恩回答的簡短補充:

你的原始版本也可以寫成如下。

(doseq [[k v] (map vector (keys db) (vals db))]
  (println (str k " " v)))

在這種情況下,這顯然是愚蠢的。 但總的來說,這也適用於不相關的輸入序列,這些輸入序列不是來自同一個 map。

如果您要解決的問題不僅僅是打印出值(副作用),這並不完全清楚,如果這就是您要解決的問題,那么我認為上面的doseq解決方案將是最慣用的。 如果你想對 map 的鍵和值做一些操作並返回相同類型的數據結構,那么你應該看看reduce-kv ,你可以在這里找到文檔

reduce一樣, reduce-kv接受 function、起始值/累加器和一些數據,但在這種情況下,數據是 map 而不是序列。 function 傳遞了三個參數:累加器、當前鍵和當前值。 如果您確實想做一些數據轉換並返回一些數據,這對我來說似乎是適合這項工作的工具。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM