Clojure中into与partition结合报错问题及Map转换方案咨询
问题解答
为什么(into {} (partition 2 [:a 1 :b 2]))会报错?
咱们先拆解核心原因:你第一个例子里(into {} [[:a 1] [:b 2]])能正常运行,是因为into向Map合并元素时,只认两种格式的元素:长度为2的向量,或者MapEntry实例。
而partition 2 [:a 1 :b 2]返回的惰性序列是((:a 1) (:b 2)),这里面的每个元素是列表(PersistentList),不是向量。当into尝试把这些列表conj到Map里时,Clojure无法将列表识别为键值对形式——它会试图把列表当作MapEntry处理,但列表本身根本不是这个类型,于是就抛出了你看到的ClassCastException。
这里要澄清:和惰性序列本身无关!你可以测试一下,把partition的结果转成二元向量序列:
(into {} (map vec (partition 2 [:a 1 :b 2]))) ;; => {:a 1, :b 2}
运行完全正常,说明只要元素是二元向量,不管是不是惰性序列,into都能处理。
把扁平键值对序列转为Map的推荐方法
最直接、简洁的方案是用apply hash-map:
(apply hash-map [:a 1 :b 2]) ;; => {:a 1, :b 2}
因为hash-map本身就支持接受可变的键值对参数,apply会把扁平序列展开成一个个参数传给它,完美适配你的场景。
另外还有几种备选方案,你可以根据需求选择:
- 先将partition结果转为二元向量再用
into:(into {} (map vec (partition 2 [:a 1 :b 2]))) - 用
reduce手动构建Map:(reduce (fn [acc [k v]] (assoc acc k v)) {} (partition 2 [:a 1 :b 2])) - 用
zipmap(需先拆分键和值):(let [[keys vals] (partition 2 [:a 1 :b 2])] (zipmap keys vals))
其中apply hash-map是处理这类扁平键值对序列最常用的方式,代码简短且易读。
内容的提问来源于stack exchange,提问作者Ben Kovitz
相关产品推荐
相关产品推荐

