11

给定一个只有关键字键的嵌套映射,例如{: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)))

如您所见,我不能flatten-map只选择“叶子”。

4

1 回答 1

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

您无条件地创建新的键/值对,即使要扩展值,所以我将 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}
于 2013-07-27T20:38:40.790 回答