11

我有一个哈希图。我想迭代这些值并根据值的类型替换它们中的每一个。如果该值是整数,则将其替换为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似乎是潜在的解决方案,但我无法完全掌握它们。

4

4 回答 4

18
(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)

警告:最后一个不适用于记录。

于 2013-01-30T07:32:00.927 回答
5

您概述的操作——独立地转换映射中的每个值——实际上已经在Functor 模块中实现。

要使用它,您需要做的是实现转换单个值的函数,然后fmap将其覆盖在您的地图上:

(fmap your-function your-map)

(不要被 fmap 这个名字误导——这个操作并不特定于映射。因为它是一个通用函数,所以它适用于任何具有 Functor 实例的东西,它还包括列表、集合和向量)。 这是一个结构保留操作:不会更改任何键,不会添加新键,也不会删除任何键。

如果您不想使用泛型函数,只需查看实现

(defmethod fmap clojure.lang.IPersistentMap
  [f m]
  (into (empty m) (for [[k v] m] [k (f v)])))  ;;; <== the important part!!

哪里f = your-functionm = your-map


此库已移动(正在移动?将移动?)到clojure.algo.generic.functor. 有关更多信息,请参阅此内容,以及内容的来源。

于 2013-01-30T11:51:39.437 回答
3
(letfn [(map-vals [m f]
          (into {} (for [[k v] m]
                     [k (f v)])))]
  (map-vals m #(= Integer (type %))))
于 2013-01-30T06:46:24.617 回答
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))))))
于 2013-01-30T07:19:33.750 回答