While searching for MultiSet or Bag resources, I found this implementation 
by Achim Passen at: A simple multiset/bag implementation for Clojure.

However, I found I could meet my needs by adding functions to treat 
vectors, or other collection types, as unordered. These can then be used 
directly, or in the definition of your own specialized types.

For the hash, from Clojure Data Structures:

(defn hash-unordered [collection]
  (-> (reduce unchecked-add-int 0 (map hash collection))
      (mix-collection-hash (count collection))))


For equality:
(defn equals-unordered [coll-a coll-b]
  "Treat collections as unordered for 1st level of comparison."
  (or (identical? coll-a coll-b)
      (and (empty? coll-a) (empty? coll-b))
      (and (= (hash-unordered coll-a) (hash-unordered coll-b))
           (let [set-a (set coll-a)
                 set-b (set coll-b)]
             (and (= set-a set-b)
                  (loop [[item & items] (seq set-a)]
                    (let [finder #(= item %)
                          found-a (filter finder coll-a)
                          found-b (filter finder coll-b)]
                      (if (not= (count found-a) (count found-b))
                        false
                        (if (empty? items)
                          true
                          (recur items))))))))))

Neither Achim's deftype, nor the above, is likely as efficient as 
implementation as a core collection MultiSet.

The attached file has a trivial implementation of a deftype showing the 
functions in use. It defines a shopping cart where the items are kept on a 
vector, which is treated as an unordered collection. A transcript of 
playing with the shopping cart follows:

user=> (load-file "shopping_cart.clj")
#'example.multi-set/make-shopping-cart
user=> (use 'example.multi-set)
nil
user=> (def cart0 (make-shopping-cart 'carrots 'beans 'eggs))
#'user/cart0
user=> cart0
(make-shopping-cart carrots beans eggs)
user=> (def cart1 (make-shopping-cart 'eggs 'carrots 'beans))
#'user/cart1
user=> cart1
(make-shopping-cart eggs carrots beans)
user=> (def cart2 (make-shopping-cart 'ham 'eggs 'carrots 'beans))
#'user/cart2
user=> cart2
(make-shopping-cart ham eggs carrots beans)
user=> (= cart0 cart1)
true
user=> (= cart1 cart2)
false  

Greg

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Attachment: shopping_cart.clj
Description: Binary data

Reply via email to