forked from clj-commons/useful
-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
113 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)]))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)))))))) |