Skip to content
Browse files

association vectors

  • Loading branch information...
1 parent beae40b commit 0f149350fb242120e1fb3c345139273e3cca2625 @ninjudd ninjudd committed Sep 28, 2012
Showing with 113 additions and 0 deletions.
  1. +56 −0 src/useful/vec.clj
  2. +57 −0 test/useful/vec_test.clj
View
56 src/useful/vec.clj
@@ -0,0 +1,56 @@
+(ns useful.vec)
+
+(defn avec-index
+ "Given an association vector, a vector where each element is a vector of key
+ and val, return the index in avec of the first element matching key."
+ [avec key]
+ (first (keep-indexed (fn [index [k v]]
+ (when (= k key)
+ index))
+ avec)))
+
+(defn avec-find
+ "Return the first elment in association vector avec matching key."
+ [avec key]
+ (get avec (avec-index avec key)))
+
+(defn avec-get
+ "Return the first value in association vector avec matching key, or not-found."
+ [avec key & [not-found]]
+ (if-let [[_ val] (avec-find avec key)]
+ val
+ not-found))
+
+(defn avec-keys
+ "Return a sequence of all the keys in association vector avec."
+ [avec]
+ (map first avec))
+
+(defn avec-vals
+ "Return a sequence of all the vals in association vector avec."
+ [avec]
+ (map second avec))
+
+(defn avec-assoc
+ "Add the given key/val pairs to the association vector avec."
+ ([avec key val]
+ (if-let [index (avec-index avec key)]
+ (assoc avec index [key val])
+ (conj avec [key val])))
+ ([avec key val & kvs]
+ (let [avec (avec-assoc avec key val)]
+ (apply avec-assoc avec kvs))))
+
+(defn avec-dissoc
+ "Remove the elements matching the given keys from the association vector avec."
+ [avec & keys]
+ (let [keys (set keys)]
+ (vec (remove #(contains? keys (first %)) avec))))
+
+(defn avec-update
+ "Update the value matching key in the association vector avec by calling f with args."
+ [avec key f & args]
+ (if-let [index (avec-index avec key)]
+ (let [val (second (get avec index))]
+ (assoc avec index [key (apply f val args)]))
+ (conj avec [key (apply f nil args)])))
View
57 test/useful/vec_test.clj
@@ -0,0 +1,57 @@
+(ns useful.vec-test
+ (:use clojure.test useful.vec))
+
+(deftest test-avec
+ (let [avec [[1 :a] [:foo [1 2 3]] ["bar" 42] [:none nil]]]
+ (testing "avec-index"
+ (is (= 0 (avec-index avec 1)))
+ (is (= 2 (avec-index avec "bar")))
+ (is (= 1 (avec-index avec :foo)))
+ (is (= nil (avec-index avec :baz))))
+ (testing "avec-find"
+ (is (= [1 :a] (avec-find avec 1)))
+ (is (= [:foo [1 2 3]] (avec-find avec :foo)))
+ (is (= ["bar" 42] (avec-find avec "bar")))
+ (is (= [:none nil] (avec-find avec :none)))
+ (is (= nil (avec-find avec 3))))
+ (testing "avec-get"
+ (is (= :a (avec-get avec 1)))
+ (is (= [1 2 3] (avec-get avec :foo)))
+ (is (= 42 (avec-get avec "bar")))
+ (is (= nil (avec-get avec 3)))
+ (is (= :nope (avec-get avec 3 :nope)))
+ (is (= :a (avec-get avec 1 :yep)))
+ (is (= nil (avec-get avec :none 42))))
+ (testing "avec-keys"
+ (is (= [1 :foo "bar" :none] (avec-keys avec))))
+ (testing "avec-vals"
+ (is (= [:a [1 2 3] 42 nil] (avec-vals avec))))
+ (testing "avec-assoc"
+ (let [bvec (avec-assoc avec 1 :one :b 4 :c 8)]
+ (is (= :one (avec-get bvec 1)))
+ (is (= 4 (avec-get bvec :b)))
+ (is (= 8 (avec-get bvec :c)))
+ (is (= [1 :foo "bar" :none :b :c] (avec-keys bvec)))
+ (let [cvec (avec-assoc bvec 1 nil :b 5)]
+ (is (= nil (avec-get cvec 1)))
+ (is (= 5 (avec-get cvec :b)))
+ (is (= [1 :foo "bar" :none :b :c] (avec-keys cvec))))))
+ (testing "avec-dissoc"
+ (let [dvec (avec-dissoc avec 1 :foo :bar)]
+ (is (= nil (avec-find dvec 1)))
+ (is (= nil (avec-find dvec :foo)))
+ (is (= ["bar" 42] (avec-find dvec "bar")))
+ (is (= ["bar" :none] (avec-keys dvec)))
+ (is (= [42 nil] (avec-vals dvec)))))
+ (testing "avec-update"
+ (let [evec (-> avec
+ (avec-update :foo conj 4)
+ (avec-update "bar" inc))]
+ (is (= :a (avec-get evec 1))) ; unchanged
+ (is (= [1 2 3 4] (avec-get evec :foo)))
+ (is (= 43 (avec-get evec "bar")))
+ (is (= [1 :foo "bar" :none] (avec-keys evec)))
+ (let [fvec (avec-update evec :new assoc :foo 1 :bar 2)]
+ (is (= {:foo 1 :bar 2} (avec-get fvec :new)))
+ (is (= :a (avec-get fvec 1))) ; unchanged
+ (is (= [1 :foo "bar" :none :new] (avec-keys fvec))))))))

0 comments on commit 0f14935

Please sign in to comment.
Something went wrong with that request. Please try again.