Just came up with two similar mapping functions in Clojure: map-grid and map-tree.
map-grid
Given a regular n-dimensional table of data, apply a function to each cell along with its index path specific to a given depth. For example, with the following 2 dimensional table:
(def table
[ [0 1 0]
[0 1 0]
[0 1 0] ])
To generate a hash-map from locations to data, one might write:
;; For rows as data:
(apply merge (flatten (map-grid 1 hash-map table)))
;; Resulting in:
;; {[1] [0 1 0],
;; [2] [0 1 0],
;; [0] [0 1 0]}
;; For cells as data
(apply merge (flatten (map-grid 2 hash-map table)))
;; Resulting in:
;; {[2 1] 1,
;; [1 0] 0,
;; [2 2] 0,
;; [0 0] 0,
;; [1 1] 1,
;; [0 1] 1,
;; [1 2] 0,
;; [0 2] 0,
;; [2 0] 0}
map-grid accepts a depth-level a function and some data. The depth-level specifies how deep to traverse the data. The function describes the transformation of a cell with access to the cells index path.
The definition of map-grid is as follows:
(defn map-grid
([depth f data] (map-grid depth f data []))
([depth f data levels]
(if (zero? depth)
(f levels data)
(map-indexed
(fn [i v]
(map-grid (dec depth) f v (conj levels i)))
data))))
map-tree
This function doesn’t allow for the depth to be specified - if a collection is found, it will iterate through it. Defined as follows:
(defn map-tree
([f data] (map-tree f data []))
([f data levels]
(if (coll? data)
(map-indexed
(fn [i v]
(map-tree f v (conj levels i)))
data)
(f levels data))))