Clojure 中哈希映射的解构和处理向量
Destructure and process vector of hash-maps in Clojure
我有一个散列映射向量,如下所示:
(def my-maps [{:a 1} {:b 2}])
我想遍历每个哈希图,在循环中为键和值赋予一个更有意义的名称,然后根据其键以不同方式处理每个哈希图。
事不宜迟,这是我最好的尝试:
(for [m my-maps]
(let [my-key-name (key m) my-val-name (val m)]
(case my-key-name
:a (println "Found key :a with value " my-val-name)
:b (println "Found key :b with value " my-val-name))))
但是,这种方法会产生一个相当神秘的错误:
; Error printing return value (ClassCastException) at clojure.core/key (core.clj:1569).
; class clojure.lang.PersistentArrayMap cannot be cast to class java.util.Map$Entry (clojure.lang.PersistentArrayMap is in unnamed module of loader 'app'; java.util.Map$Entry is in module java.base of loader 'bootstrap')
我做错了什么?
(for [[[k v] & _] [{:a 1} {:b 2}]]
(println "Found key" k "with value" v))
Found key :a with value 1
Found key :b with value 2
=> (nil nil)
为了清楚起见,这里有一个更笼统的答案,分为各个步骤:
(let [my-maps [{:a 1} {:b 2 :c 3}]]
(doseq [curr-map my-maps]
(newline)
(println "curr-map=" curr-map)
(let [map-entries (seq curr-map)]
(println "map-entries=" map-entries)
(doseq [curr-me map-entries]
(let [[k v] curr-me]
(println " curr-me=" curr-me " k=" k " v=" v))))))
有结果
curr-map= {:a 1}
map-entries= ([:a 1])
curr-me= [:a 1] k= :a v= 1
curr-map= {:b 2, :c 3}
map-entries= ([:b 2] [:c 3])
curr-me= [:b 2] k= :b v= 2
curr-me= [:c 3] k= :c v= 3
Clojure 中的 MapEntry
对象可以被视为二元向量(通过 first
& second
访问)或作为 MapEntry
通过key
和 val
函数。解构形式:
(let [[k v] curr-me]
将 MapEntry
对象 curr-me
视为一个序列,并将前 2 个元素提取到 k
和 v
中。尽管它像矢量一样打印(例如 [:a 1]
),但它确实具有 clojure.lang.MapEntry
.
类型
原始答案的 for
表达式中的解构语法 & _
是“rest args”解构。它导致第一个对象之后的所有 MapEntry
个对象的序列被分配给变量 _
,然后在其余代码中被忽略。
我有一个散列映射向量,如下所示:
(def my-maps [{:a 1} {:b 2}])
我想遍历每个哈希图,在循环中为键和值赋予一个更有意义的名称,然后根据其键以不同方式处理每个哈希图。
事不宜迟,这是我最好的尝试:
(for [m my-maps]
(let [my-key-name (key m) my-val-name (val m)]
(case my-key-name
:a (println "Found key :a with value " my-val-name)
:b (println "Found key :b with value " my-val-name))))
但是,这种方法会产生一个相当神秘的错误:
; Error printing return value (ClassCastException) at clojure.core/key (core.clj:1569).
; class clojure.lang.PersistentArrayMap cannot be cast to class java.util.Map$Entry (clojure.lang.PersistentArrayMap is in unnamed module of loader 'app'; java.util.Map$Entry is in module java.base of loader 'bootstrap')
我做错了什么?
(for [[[k v] & _] [{:a 1} {:b 2}]]
(println "Found key" k "with value" v))
Found key :a with value 1
Found key :b with value 2
=> (nil nil)
为了清楚起见,这里有一个更笼统的答案,分为各个步骤:
(let [my-maps [{:a 1} {:b 2 :c 3}]]
(doseq [curr-map my-maps]
(newline)
(println "curr-map=" curr-map)
(let [map-entries (seq curr-map)]
(println "map-entries=" map-entries)
(doseq [curr-me map-entries]
(let [[k v] curr-me]
(println " curr-me=" curr-me " k=" k " v=" v))))))
有结果
curr-map= {:a 1}
map-entries= ([:a 1])
curr-me= [:a 1] k= :a v= 1
curr-map= {:b 2, :c 3}
map-entries= ([:b 2] [:c 3])
curr-me= [:b 2] k= :b v= 2
curr-me= [:c 3] k= :c v= 3
Clojure 中的 MapEntry
对象可以被视为二元向量(通过 first
& second
访问)或作为 MapEntry
通过key
和 val
函数。解构形式:
(let [[k v] curr-me]
将 MapEntry
对象 curr-me
视为一个序列,并将前 2 个元素提取到 k
和 v
中。尽管它像矢量一样打印(例如 [:a 1]
),但它确实具有 clojure.lang.MapEntry
.
原始答案的 for
表达式中的解构语法 & _
是“rest args”解构。它导致第一个对象之后的所有 MapEntry
个对象的序列被分配给变量 _
,然后在其余代码中被忽略。