通过加入键来展平地图

Mar*_*gan 11 clojure

给定一个只有关键字键的嵌套映射{:foo {:bar 1 :baz [2 3] :qux {:quux 4}} :corge 5},如何实现,flatten-map以便(flatten-map {:foo {:bar 1 :baz [2 3] :qux {:quux 4}} :corge 5} "-")产生类似的东西{:foo-bar 1 :foo-baz [2 3] :foo-qux-quux 4 :corge 5}.

我最好的尝试是:

(defn flatten-map
  ([form separator] (flatten-map form separator nil))
  ([form separator prefix]
  (if (map? form)
    (into {} (map (fn [[k v]]
                    [(keyword (str prefix (name k)))
                     (flatten-map v separator (str prefix (name k) separator))])
                  form))
    form)))
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我不能flatten-map只选择"叶子".

noi*_*ith 13

(defn flatten-map
  ([form separator]
     (into {} (flatten-map form separator nil)))
  ([form separator pre]
     (mapcat (fn [[k v]]
               (let [prefix (if pre (str pre separator (name k)) (name k))]
                 (if (map? v)
                   (flatten-map v separator prefix)
                   [[(keyword prefix) v]])))
               form)))
Run Code Online (Sandbox Code Playgroud)

您无条件地创建新的键/值对,即使要扩展该值,所以我将map切换到mapcat,以便将结果"包含"到顶层(这也需要将其(into {} ...)分成顶级版本形式,因为我们实际上并不想要任何地图,只有输出的顶层.

以下是它如何与您的示例一起使用:

user> (flatten-map {:foo {:bar 1 :baz [2 3] :qux {:quux 4}} :corge 5} "-")
{:foo-bar 1, :foo-qux-quux 4, :foo-baz [2 3], :corge 5}
Run Code Online (Sandbox Code Playgroud)