Clojure多地图

8 clojure

非常简单+愚蠢的问题:

clojure提供多张地图吗?我目前有这样的事情:

(defn wrap [func]
  (fn [mp x]
    (let [k (func x)]
      (assoc mp k
             (match (get mp k)
               nil [x]
               v (cons v x))))))

(defn create-mm [func lst]
  (reduce (wrap func) {} lst))
Run Code Online (Sandbox Code Playgroud)

最终创建了一个地图,对于每个键,我们有一个包含该键的所有元素的向量.然而,似乎多地图是一个非常基本的数据结构,我想知道clojure是否内置了它.

谢谢

Nic*_*uer 11

我不认为这是一个独特的类型,因为Clojure的灵活性允许您通过使用地图和集合快速制作自己的.看这里:

http://paste.lisp.org/display/89840

编辑(我应该刚刚粘贴它,因为它太小了)

示例代码(由Stuart Sierra提供)

(ns #^{:doc "A multimap is a map that permits multiple values for each
  key.  In Clojure we can represent a multimap as a map with sets as
  values."}
  multimap
  (:use [clojure.set :only (union)]))

(defn add
  "Adds key-value pairs the multimap."
  ([mm k v]
     (assoc mm k (conj (get mm k #{}) v)))
  ([mm k v & kvs]
     (apply add (add mm k v) kvs)))

(defn del
  "Removes key-value pairs from the multimap."
  ([mm k v]
     (let [mmv (disj (get mm k) v)]
       (if (seq mmv)
         (assoc mm k mmv)
         (dissoc mm k))))
  ([mm k v & kvs]
     (apply del (del mm k v) kvs)))

(defn mm-merge
  "Merges the multimaps, taking the union of values."
  [& mms]
  (apply (partial merge-with union) mms))

(comment
  (def mm (add {} :foo 1 :foo 2 :foo 3))
  ;; mm == {:foo #{1 2 3}}

  (mm-merge mm (add {} :foo 4 :bar 2))
  ;;=> {:bar #{2}, :foo #{1 2 3 4}}

  (del mm :foo 2)
  ;;=> {:foo #{1 3}}
)
Run Code Online (Sandbox Code Playgroud)

评论中指出的案件的额外测试:

(comment
  (-> {} (add :a 1) (del :a 1) (contains? :a))
  ;;=> false
)
Run Code Online (Sandbox Code Playgroud)

  • 将该代码复制到您的答案中(使用适当的属性等)可能是一个好主意,这样您的答案就会独立,以防链接失效. (2认同)
  • 请注意`( - > {}(add:a 1)(del:a 1)(包含?:a); => true`,这会让很多用户感到惊讶.对`del`的一个小修改就可以解决这个问题. (2认同)