【问题标题】:changing nested map value without knowing keys在不知道键的情况下更改嵌套映射值
【发布时间】:2015-12-11 17:49:22
【问题描述】:

我需要更改嵌套映射中的值,而我事先不知道键的值。为此,我想出了以下方法。

;; input  {String {String [String]}}
;; output {String {String String}}

(defn join-z
  [x-to-y-to-z]
  (zipmap (keys x-to-y-to-z)
          (map (fn [y-to-z] (into {} (map (fn [[y z]] {y (clojure.string/join z)})
                                          (seq y-to-z))))
               (seq (vals x-to-y-to-z)))))

(def example
  {"a" {"b" ["c" "d" "e"]}
   "m" {"n" ["o" "p"]}})

;; (join-z example) => {"m" {"n" "op"}, "a" {"b" "cde"}}

这似乎是一个黑客。这样做的惯用 clojure 是什么?或者,是否可以使用 Haskell 的镜头库之类的东西?

更新:基于user5187212 答案

(defn update-vals [f m0]
  (reduce-kv (fn [m k v] (assoc m k (f v)))
             {}
             m0))

;; (update-vals clojure.string/join {"b" ["c" "d" "e"]}) => {"b" "cde"}

(defn join-z [x-to-y-to-z]
  (update-vals (partial update-vals clojure.string/join) x-to-y-to-z))

;; (join-z example) => {"m" {"n" "op"}, "a" {"b" "cde"}}

这看起来更优雅。谢谢!

【问题讨论】:

    标签: clojure


    【解决方案1】:

    我建议reduce-kv。

    对于最后一层,你可以使用类似的东西:

    (defn foo [x]
      (reduce-kv
        (fn [m k v]
          (assoc m k (clojure.string/join v)))
        {}
        x))
    

    然后根据需要多次调用它...

    (reduce-kv 
       (fn [m k v]
         (assoc m k (foo v)))
       {} 
       example)
    

    另一种方法可能是all nested keys 然后

    (reduce 
      (fn [m ks]
        (update-in m ks clojure.string/join))
      example
      all-nested-keys)
    

    【讨论】:

      【解决方案2】:

      简短的回答是肯定的,你就是这样做的:)

      我会选择更像这样的东西:

      (into {} (for [[k v] example]
                 [k (into {} (for [[k2 v2] v]
                               [k2 (string/join v2)]))]))
      

      这几乎是一回事。

      有一个名为 Spectre 的库 https://github.com/nathanmarz/specter 对于查询和转换:

      (ns specter.core
        (:require
         [clojure.string :as string]
         [com.rpl.specter :as s]))
      
      (def example
        {"a" {"b" ["c" "d" "e"]}
         "m" {"n" ["o" "p"]}})
      
      (s/transform
       [s/ALL s/LAST s/ALL s/LAST]
       string/join
       example)
      

      我认为这是一种非常简洁的表达方式。

      【讨论】:

        猜你喜欢
        • 2019-12-13
        • 1970-01-01
        • 1970-01-01
        • 2018-06-11
        • 2015-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-08
        相关资源
        最近更新 更多