This simple solution is symetrical, stores both rows and colums and this way you get instant access both to any column and row with constant penalty on get, assoc and update.
It feels a bit messy because you decided to not differentiate between horizontal and vertical indices. That may be a good choice and give nice code later, but is somewhat surprising (you must be sure that sets of horizontal and vertical indices are disjoint). (defn get2d ([t i] (into (into {} ((first t) i)) ((second t) i))) ([t x y] (if-let [res (get-in (first t) [x y])] res (get-in (second t) [x y])))) (defn assoc2d [[rows cols] [x y] v] [(assoc-in rows [x y] v) (assoc-in cols [y x] v)]) Your example: user=> (def foo (-> [] (assoc2d [1 :C] '[x y z]) (assoc2d [2 :A] "2a") (assoc2d [2 :B] "2b") (assoc2d [3 :A] :3a) (assoc2d [3 :C] "Foo"))) #'user/foo user=> foo [{3 {:C "Foo", :A :3a}, 2 {:B "2b", :A "2a"}, 1 {:C [x y z]}} {:B {2 "2b"}, :A {3 :3a, 2 "2a"}, :C {3 "Foo", 1 [x y z]}}] user=> (get2d foo :A) {3 :3a, 2 "2a"} user=> (get2d foo 2) {:B "2b", :A "2a"} user=> (get2d foo :A 2) "2a" user=> (get2d foo 2 :A) "2a" Please note the double into in get2d. Simple (into ((first t) i) ((second t) i)) doesn't work as expected when first argument is nil. To make get2d and assoc2d more consistent one could remove brackets around [x y] in the argument list of assoc2d. -- -- 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/groups/opt_out.