我有一个哈希映射。我想迭代值并根据值的类型替换它们中的每一个。如果该值是整数,请将其替换为true
,如果不是,请将其替换为false
。我想让它返回一个新的哈希映射,每个值都更新为true或false。
(defn my-function [hash-map]
(loop [hash-map hash-map]
(for [value (vals hash-map)]
(if (= Integer (type value))
(recur (assoc hash-map key true))
(recur (assoc hash-map key false))))))
这不会起作用,因为Clojure Can only recur from tail position
,但这是我想要做的一般想法。有任何想法的有效方法吗? if-let
和update-in
似乎是潜在的解决方案,但我无法理解它们。
答案 0 :(得分:17)
(reduce-kv (fn [m k v] (assoc m k (= Integer (type v)))) {} m)
如果您愿意,甚至更短:
(reduce-kv #(assoc %1 %2 (= Integer (type %3))) {} m)
保持地图类型(哈希与排序):
(reduce-kv #(assoc %1 %2 (= Integer (type %3))) (empty m) m)
警告:最后一个不适用于记录。
答案 1 :(得分:5)
您概述的操作 - 独立地转换地图中的每个值 - 实际上已在the Functor module中实现。
使用它需要做的是实现转换单个值的函数,然后将fmap
转换为地图:
(fmap your-function your-map)
(不要被名称fmap误导 - 此操作不是特定于地图。因为它是一个通用函数,它适用于任何具有Functor实例的东西,其中还包括列表,集合和这是一个结构保留操作:不会更改任何键,也不会添加任何新键,不会删除任何键。
如果您不想使用通用功能,请查看the implementation:
(defmethod fmap clojure.lang.IPersistentMap
[f m]
(into (empty m) (for [[k v] m] [k (f v)]))) ;;; <== the important part!!
其中f = your-function
和m = your-map
。
此库已被移动(正在移动?将被移动?)到clojure.algo.generic.functor
。有关详情,请参阅this;有关来源,请参阅this。
答案 2 :(得分:3)
(letfn [(map-vals [m f]
(into {} (for [[k v] m]
[k (f v)])))]
(map-vals m #(= Integer (type %))))
答案 3 :(得分:0)
(defn f [m]
(reduce (fn [res [k v]]
(assoc res k (= Integer (type v))))
{} m))
或者如果你需要递归版
(defn f
([m] (f {} m))
([res m] (if (empty? m)
res
(let [[k v] (first m)]
(recur (assoc res k (= Integer (type v)))
(rest m))))))