在Clojure里面翻出哈希图

Dav*_*aid 8 clojure

我是Clojure的新手,并为你的Clojure大师提出了一个有趣的问题.我正在编写"编程集体智能"一书,并尝试在Clojure中编写示例代码(本书将它们全部用Python编写).在第一章中,我们有一个电影评论家的哈希映射设置和他们给不同电影的排名.它看起来像这样:

{"Lisa Rose" {"Lady in the Water" 2.5, "Snakes on a Plane" 3.5 },
 "Gene Seymour" {"Lady in the Water" 3.0, "Snakes on a Plane" 3.5}}
Run Code Online (Sandbox Code Playgroud)

问题是这个.如何将其内部转出,以便我得到一个如下所示的哈希映射:

{"Lady in the Water" {"Lisa Rose" 2.5, "Gene Seymour" 3.0},
 "Snakes on a Plane" {"Lisa Rose" 3.5, "Gene Seymour" 3.5}}
Run Code Online (Sandbox Code Playgroud)

你有什么功能来实现这个目标?

ama*_*loy 17

(let [m {"Lisa Rose" {"Lady in the Water" 2.5, "Snakes on a Plane" 3.5 },
         "Gene Seymour" {"Lady in the Water" 3.0, "Snakes on a Plane" 3.5}}]
  (apply merge-with merge
         (for [[ok ov] m
               [ik iv] ov]
           {ik {ok iv}})))

{"Snakes on a Plane" {"Gene Seymour" 3.5, "Lisa Rose" 3.5},
 "Lady in the Water" {"Gene Seymour" 3.0, "Lisa Rose" 2.5}}
Run Code Online (Sandbox Code Playgroud)


Mic*_*zyk 6

(defn inverse-map [m]
  (let [inner-keys (-> m first val keys)
        outer-keys (keys m)]
    (apply merge-with merge
           (for [ik inner-keys
                 ok outer-keys]
             {ik {ok (get-in input [ok ik])}}))))
Run Code Online (Sandbox Code Playgroud)

这假设内部地图中的所有感兴趣的关键字都出现在第一个内部地图上.如果这是不正确的,(-> m first val keys)则必须用返回所有感兴趣键的集合的东西替换,例如(->> m (map values) (mapcat keys)).

我们的想法是构建表单的地图{inner-key {outer-key the-value-at-inner-key-in-the-map-at-outer-key}},然后将它们合适地合并在一起.

问题文本中地图上的返回值是指定的.

现在,上面创建了许多中间结构,这可能是性能方面的问题.如果速度至关重要,您可以切换到loop瞬态:

(defn transient-inverse-map [m]
  (let [inner-keys (-> m first val keys)
        outer-keys (keys m)
        t (transient {})]
    (loop [inner-keys inner-keys
           t t]
      (if (seq inner-keys)
        (recur (next inner-keys)
               (assoc! t ik
                       (let [ik (first inner-keys)
                             t  (transient {})]
                         (loop [outer-keys outer-keys
                                t t]
                           (if (seq outer-keys)
                             (let [ok (first outer-keys)]
                               (recur (next outer-keys)
                                      (assoc! t ok (get-in m [ok ik]))))
                             (persistent! t))))))
        (persistent! t)))))
Run Code Online (Sandbox Code Playgroud)

这个想法是相同的,如果难以从代码中辨别出来的话.